LCOV - code coverage report
Current view: top level - src - layout.c (source / functions) Coverage Total Hit
Test: PHP Pango Extension Coverage Lines: 96.9 % 387 375
Test Date: 2025-10-26 00:52:08 Functions: 100.0 % 55 55

            Line data    Source code
       1              : /*
       2              :   +----------------------------------------------------------------------+
       3              :   | For PHP Version 8.2+                                                 |
       4              :   +----------------------------------------------------------------------+
       5              :   | Copyright (c) The PHP Group                                          |
       6              :   +----------------------------------------------------------------------+
       7              :   | This source file is subject to version 3.01 of the PHP license,      |
       8              :   | that is bundled with this package in the file LICENSE, and is        |
       9              :   | available through the world-wide-web at the following url:           |
      10              :   | http://www.php.net/license/3_01.txt                                  |
      11              :   | If you did not receive a copy of the PHP license and are unable to   |
      12              :   | obtain it through the world-wide-web, please send a note to          |
      13              :   | license@php.net so we can mail you a copy immediately.               |
      14              :   +----------------------------------------------------------------------+
      15              :   | Authors: Michael Maclean <mgdm@php.net>                              |
      16              :   |          David MarĂ­n <davefx@gmail.com>                              |
      17              :   |          Marcel Bolten <github@marcelbolten.de>                      |
      18              :   +----------------------------------------------------------------------+
      19              : */
      20              : 
      21              : #ifdef HAVE_CONFIG_H
      22              : #include "config.h"
      23              : #endif
      24              : 
      25              : #include "php.h"
      26              : #include "php_pango.h"
      27              : #include "layout_arginfo.h"
      28              : 
      29              : #include "zend_exceptions.h"
      30              : 
      31              : zend_class_entry *pango_ce_pango_layout;
      32              : zend_class_entry *pango_ce_pango_alignment;
      33              : zend_class_entry *pango_ce_pango_wrap_mode;
      34              : zend_class_entry *pango_ce_pango_ellipsize_mode;
      35              : 
      36          194 : PHP_PANGO_API zend_class_entry* php_pango_get_layout_ce() {
      37          194 :     return pango_ce_pango_layout;
      38              : }
      39              : 
      40              : static zend_object_handlers pango_layout_object_handlers;
      41              : 
      42          343 : pango_layout_object *pango_layout_fetch_object(zend_object *object)
      43              : {
      44          343 :     return (pango_layout_object *) ((char*)(object) - XtOffsetOf(pango_layout_object, std));
      45              : }
      46              : 
      47              : /* {{{ Creates a PangoLayout based on the Pango Context object */
      48           60 : PHP_METHOD(Pango_Layout, __construct)
      49              : {
      50           60 :     zval *context_zval = NULL;
      51              :     pango_context_object *context_object;
      52              :     pango_layout_object *layout_object;
      53              : 
      54           60 :     ZEND_PARSE_PARAMETERS_START(1, 1)
      55          116 :         Z_PARAM_OBJECT_OF_CLASS(context_zval, php_pango_get_context_ce())
      56           60 :     ZEND_PARSE_PARAMETERS_END();
      57              : 
      58           57 :     context_object = Z_PANGO_CONTEXT_P(context_zval);
      59              : 
      60          114 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
      61           57 :     layout_object->layout = pango_layout_new(context_object->context);
      62              : 
      63           57 :     if (layout_object->layout == NULL) {
      64            0 :         zend_throw_exception(
      65              :             pango_ce_pango_exception,
      66              :             "Could not create the Pango layout",
      67              :             0
      68              :         );
      69            0 :         RETURN_THROWS();
      70              :     }
      71              : 
      72           57 :     ZVAL_COPY(&layout_object->pango_context_zv, context_zval);
      73              : }
      74              : /* }}} */
      75              : 
      76              : /* {{{ Return the PangoContext for the current layout */
      77            3 : PHP_METHOD(Pango_Layout, getContext)
      78              : {
      79              :     pango_layout_object *layout_object;
      80              :     pango_context_object *context_object;
      81              :     PangoContext *context;
      82              : 
      83            3 :     ZEND_PARSE_PARAMETERS_NONE();
      84              : 
      85            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
      86              : 
      87            4 :     if (Z_TYPE(layout_object->pango_context_zv) != IS_UNDEF) {
      88            2 :         ZVAL_COPY(return_value, &layout_object->pango_context_zv);
      89              :     } else {
      90            0 :         object_init_ex(return_value, php_pango_get_context_ce());
      91              :     }
      92              : 
      93              :     /* Get the context_object */
      94            2 :     context_object = Z_PANGO_CONTEXT_P(return_value);
      95              :     /* Destroy an existing pango context cause we're getting a new one */
      96            2 :     if (context_object->context != NULL) {
      97            2 :         g_object_unref(context_object->context);
      98              :     }
      99              : 
     100              :     /* (Re-)Set the internal pango context pointer */
     101            2 :     context_object->context = pango_layout_get_context(layout_object->layout);
     102            2 :     g_object_ref(context_object->context);
     103              : 
     104              :     // Store the pango context zval in the layout object for later reuse
     105              :     // ZVAL_COPY(&layout_object->pango_context_zv, return_value);
     106              : }
     107              : /* }}} */
     108              : 
     109              : /* {{{ Sets the text of the layout. */
     110           36 : PHP_METHOD(Pango_Layout, setText)
     111              : {
     112              :     pango_layout_object *layout_object;
     113              :     char *text;
     114              :     size_t text_len;
     115              : 
     116           36 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     117           68 :         Z_PARAM_STRING(text, text_len)
     118           36 :     ZEND_PARSE_PARAMETERS_END();
     119              : 
     120           66 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     121              : 
     122              :     // The text will also be truncated on encountering a nul-termination even when length is positive.
     123              :     // That is problematic as php allows embedded nuls in strings.
     124              :     // check if text contains a null byte and warn the user
     125           33 :     if (memchr(text, '\0', text_len) != NULL) {
     126            1 :         zend_error(E_NOTICE, "Text contains null byte and will be truncated.");
     127              :     }
     128           33 :     pango_layout_set_text(layout_object->layout, text, text_len);
     129              : }
     130              : /* }}} */
     131              : 
     132              : /* {{{ Gets the text currently in the layout */
     133           23 : PHP_METHOD(Pango_Layout, getText)
     134              : {
     135              :     pango_layout_object *layout_object;
     136              :     const char *text;
     137              : 
     138           23 :     ZEND_PARSE_PARAMETERS_NONE();
     139              : 
     140           44 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     141           22 :     if (text = pango_layout_get_text(layout_object->layout)) {
     142           44 :         RETURN_STRING((char *)text);
     143              :     }
     144            0 :     RETURN_EMPTY_STRING();
     145              : }
     146              : /* }}} */
     147              : 
     148              : /* {{{ Sets the markup of the layout. */
     149           13 : PHP_METHOD(Pango_Layout, setMarkup)
     150              : {
     151           13 :     zval *layout_zval = NULL;
     152              :     pango_layout_object *layout_object;
     153              :     char *markup;
     154              :     size_t markup_len;
     155              : 
     156           13 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     157           22 :         Z_PARAM_STRING(markup, markup_len)
     158           13 :     ZEND_PARSE_PARAMETERS_END();
     159              : 
     160           20 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     161              : 
     162              :     // The text may be truncated on encountering a null byte even when length is positive.
     163              :     // That is problematic as php allows embedded nuls in strings.
     164              :     // Check if markup contains a null byte and warn the user
     165           10 :     if (memchr(markup, '\0', markup_len) != NULL) {
     166            7 :         zend_error(E_NOTICE, "Pango\\Pango::setMarkup(): Markup contains null byte. "
     167              :             "This may cause the underlying pango markup parser to fail, "
     168              :             "the text may be truncated, or not be set."
     169              :         );
     170              :     }
     171              : 
     172           10 :     pango_layout_set_markup(layout_object->layout, markup, markup_len);
     173              : }
     174              : /* }}} */
     175              : 
     176              : /* {{{ Updates the private PangoContext of a PangoLayout to match the current transformation
     177              :        and target surface of a Cairo context.
     178              :        PARAMS ARE REVERSED FROM NATIVE PANGO */
     179            2 : PHP_METHOD(Pango_Layout, contextChanged)
     180              : {
     181              :     pango_layout_object *layout_object;
     182              : 
     183            2 :     ZEND_PARSE_PARAMETERS_NONE();
     184              : 
     185            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     186            1 :     pango_layout_context_changed(layout_object->layout);
     187              : }
     188              : /* }}} */
     189              : 
     190              : /* {{{ Sets the markup of the layout with accelerator markers. */
     191           13 : PHP_METHOD(Pango_Layout, setMarkupWithAccel)
     192              : {
     193              :     pango_layout_object *layout_object;
     194              :     char *markup;
     195           13 :     size_t markup_len = 0;
     196              :     char *accel_marker;
     197           13 :     size_t accel_marker_len = 0;
     198           13 :     gunichar first_accel_codepoint = 0;
     199           13 :     gunichar accel_marker_char = 0;
     200              :     char first_accel_char[6];  // Max UTF-8 char is 6 bytes
     201              :     int first_accel_char_len;
     202              : 
     203           13 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     204           22 :         Z_PARAM_STRING(markup, markup_len)
     205           20 :         Z_PARAM_STRING(accel_marker, accel_marker_len)
     206           13 :     ZEND_PARSE_PARAMETERS_END();
     207              : 
     208           18 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     209              : 
     210            9 :     if (memchr(markup, '\0', markup_len) != NULL) {
     211            7 :         zend_error(E_NOTICE, "Pango\\Pango::setMarkupWithAccel(): Markup contains null byte. "
     212              :             "This may cause the underlying pango markup parser to fail, "
     213              :             "the text may be truncated, or not be set."
     214              :         );
     215              :     }
     216              : 
     217              :     // Convert UTF-8 string to gunichar
     218            9 :     if (accel_marker_len > 0) {
     219            8 :         accel_marker_char = g_utf8_get_char(accel_marker);
     220              :     }
     221              : 
     222            9 :     pango_layout_set_markup_with_accel(
     223              :         layout_object->layout,
     224              :         markup,
     225              :         markup_len,
     226              :         accel_marker_char,
     227              :         &first_accel_codepoint
     228              :     );
     229              : 
     230            9 :     if (first_accel_codepoint == 0) {
     231            5 :         RETURN_EMPTY_STRING();
     232              :     }
     233              : 
     234            4 :     first_accel_char_len = g_unichar_to_utf8(first_accel_codepoint, first_accel_char);
     235            8 :     RETURN_STRINGL(first_accel_char, first_accel_char_len);
     236              : }
     237              : /* }}} */
     238              : 
     239              : /* {{{ Gets the width of the layout. */
     240            7 : PHP_METHOD(Pango_Layout, getWidth)
     241              : {
     242              :     pango_layout_object *layout_object;
     243              :     long width;
     244              : 
     245            7 :     ZEND_PARSE_PARAMETERS_NONE();
     246              : 
     247           12 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     248            6 :     width = pango_layout_get_width(layout_object->layout);
     249            6 :     RETURN_LONG(width);
     250              : }
     251              : /* }}} */
     252              : 
     253              : /* {{{ Gets the height of the layout. */
     254            7 : PHP_METHOD(Pango_Layout, getHeight)
     255              : {
     256              :     pango_layout_object *layout_object;
     257              :     long height;
     258              : 
     259            7 :     ZEND_PARSE_PARAMETERS_NONE();
     260              : 
     261           12 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     262            6 :     height = pango_layout_get_height(layout_object->layout);
     263            6 :     RETURN_LONG((zend_long) height);
     264              : }
     265              : /* }}} */
     266              : 
     267              : /* {{{ Gets the size of the layout. */
     268            3 : PHP_METHOD(Pango_Layout, getSize)
     269              : {
     270              :     pango_layout_object *layout_object;
     271            3 :     int height = 0, width = 0;
     272              : 
     273            3 :     ZEND_PARSE_PARAMETERS_NONE();
     274              : 
     275            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     276            2 :     if (!layout_object->layout) {
     277            0 :         RETURN_NULL();
     278              :     }
     279            2 :     pango_layout_get_size(layout_object->layout, &width, &height);
     280              : 
     281              :     // TODO: don't return an array but an object with properties
     282            2 :     array_init(return_value);
     283            2 :     add_assoc_long(return_value, "width", (zend_long) width);
     284            2 :     add_assoc_long(return_value, "height", (zend_long) height);
     285              : }
     286              : /* }}} */
     287              : 
     288              : /* {{{ Gets the size of layout in pixels */
     289            3 : PHP_METHOD(Pango_Layout, getPixelSize)
     290              : {
     291            3 :     zval *layout_zval = NULL;
     292              :     pango_layout_object *layout_object;
     293            3 :     int height = 0, width = 0;
     294              : 
     295            3 :     ZEND_PARSE_PARAMETERS_NONE();
     296              : 
     297            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     298            2 :     pango_layout_get_pixel_size(layout_object->layout, &width, &height);
     299              : 
     300              :     // TODO: don't return an array but an object with properties
     301            2 :     array_init(return_value);
     302            2 :     add_assoc_long(return_value, "width", width);
     303            2 :     add_assoc_long(return_value, "height", height);
     304              : }
     305              : /* }}} */
     306              : 
     307              : /* {{{ Gets the extents of layout in */
     308            3 : PHP_METHOD(Pango_Layout, getExtents)
     309              : {
     310              :     pango_layout_object *layout_object;
     311              :     PangoRectangle pango_ink_rect;
     312              :     PangoRectangle pango_logical_rect;
     313              :     zval ink_rect_zv;
     314              :     zval logical_rect_zv;
     315              : 
     316            3 :     ZEND_PARSE_PARAMETERS_NONE();
     317              : 
     318            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     319            2 :     pango_layout_get_extents(layout_object->layout, &pango_ink_rect, &pango_logical_rect);
     320              : 
     321            2 :     array_init(return_value);
     322            2 :     object_init_ex(&ink_rect_zv, php_pango_get_rectangle_ce());
     323            2 :     *pango_rectangle_object_get_rectangle(&ink_rect_zv) = pango_ink_rect;
     324              :     add_assoc_zval(return_value, "ink", &ink_rect_zv);
     325              : 
     326            2 :     object_init_ex(&logical_rect_zv, php_pango_get_rectangle_ce());
     327            2 :     *pango_rectangle_object_get_rectangle(&logical_rect_zv) = pango_logical_rect;
     328              :     add_assoc_zval(return_value, "logical", &logical_rect_zv);
     329              : }
     330              : /* }}} */
     331              : 
     332              : /* {{{ Gets the extents of layout in pixels */
     333            3 : PHP_METHOD(Pango_Layout, getPixelExtents)
     334              : {
     335              :     pango_layout_object *layout_object;
     336              :     PangoRectangle pango_ink_rect;
     337              :     PangoRectangle pango_logical_rect;
     338              :     zval ink_rect_zv;
     339              :     zval logical_rect_zv;
     340              : 
     341            3 :     ZEND_PARSE_PARAMETERS_NONE();
     342              : 
     343            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     344            2 :     pango_layout_get_pixel_extents(layout_object->layout, &pango_ink_rect, &pango_logical_rect);
     345              : 
     346            2 :     array_init(return_value);
     347            2 :     object_init_ex(&ink_rect_zv, php_pango_get_rectangle_ce());
     348            2 :     *pango_rectangle_object_get_rectangle(&ink_rect_zv) = pango_ink_rect;
     349              :     add_assoc_zval(return_value, "ink", &ink_rect_zv);
     350              : 
     351            2 :     object_init_ex(&logical_rect_zv, php_pango_get_rectangle_ce());
     352            2 :     *pango_rectangle_object_get_rectangle(&logical_rect_zv) = pango_logical_rect;
     353              :     add_assoc_zval(return_value, "logical", &logical_rect_zv);
     354              : }
     355              : /* }}} */
     356              : 
     357              : /* {{{ Sets the width of the layout. */
     358           10 : PHP_METHOD(Pango_Layout, setWidth)
     359              : {
     360              :     pango_layout_object *layout_object;
     361              :     zend_long width;
     362              : 
     363           10 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     364           16 :         Z_PARAM_LONG(width)
     365           10 :     ZEND_PARSE_PARAMETERS_END();
     366              : 
     367           14 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     368            7 :     pango_layout_set_width(layout_object->layout, width);
     369              : }
     370              : /* }}} */
     371              : 
     372              : /* {{{ Sets the height of the layout. */
     373            8 : PHP_METHOD(Pango_Layout, setHeight)
     374              : {
     375              :     pango_layout_object *layout_object;
     376              :     zend_long height;
     377              : 
     378            8 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     379           12 :         Z_PARAM_LONG(height)
     380            8 :     ZEND_PARSE_PARAMETERS_END();
     381              : 
     382           10 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     383            5 :     pango_layout_set_height(layout_object->layout, height);
     384              : }
     385              : /* }}} */
     386              : 
     387              : /* {{{ Sets the font_description of the layout. */
     388            4 : PHP_METHOD(Pango_Layout, setFontDescription)
     389              : {
     390            4 :     zval *font_desc_zv = NULL;
     391              :     pango_layout_object *layout_object;
     392              :     pango_font_description_object *font_description_object;
     393              : 
     394            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     395            4 :         Z_PARAM_OBJECT_OF_CLASS(font_desc_zv, php_pango_get_font_description_ce())
     396            4 :     ZEND_PARSE_PARAMETERS_END();
     397              : 
     398            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     399            1 :     font_description_object = Z_PANGO_FONT_DESC_P(font_desc_zv);
     400            1 :     pango_layout_set_font_description(layout_object->layout, font_description_object->font_description);
     401              : }
     402              : /* }}} */
     403              : 
     404              : /* {{{ Gets the font_description of the layout. */
     405            4 : PHP_METHOD(Pango_Layout, getFontDescription)
     406              : {
     407              :     pango_layout_object *layout_object;
     408            4 :     pango_font_description_object *font_description_object = NULL;
     409            4 :     const PangoFontDescription *font_description = NULL;
     410              : 
     411            4 :     ZEND_PARSE_PARAMETERS_NONE();
     412              : 
     413            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     414              : 
     415              :     // font_description can be NULL, in that case the font description is from the context and not set on the layout
     416            3 :     if (!(font_description = pango_layout_get_font_description(layout_object->layout))) {
     417              :         // TODO: should the font description of the context be returned instead?
     418            2 :         RETURN_NULL();
     419              :     }
     420              : 
     421            1 :     object_init_ex(return_value, php_pango_get_font_description_ce());
     422            1 :     font_description_object = Z_PANGO_FONT_DESC_P(return_value);
     423            1 :     font_description_object->font_description = pango_font_description_copy(font_description);
     424              : }
     425              : /* }}} */
     426              : 
     427              : /* {{{ Sets whether each line should be justified. */
     428            5 : PHP_METHOD(Pango_Layout, setJustify)
     429              : {
     430              :     pango_layout_object *layout_object;
     431              :     bool justify;
     432              : 
     433            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     434            8 :         Z_PARAM_BOOL(justify)
     435            5 :     ZEND_PARSE_PARAMETERS_END();
     436              : 
     437            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     438            3 :     pango_layout_set_justify(layout_object->layout, justify);
     439              : }
     440              : /* }}} */
     441              : 
     442              : /* {{{ Returns whether text will be justified or not in the current layout */
     443            3 : PHP_METHOD(Pango_Layout, getJustify)
     444              : {    pango_layout_object *layout_object;
     445              : 
     446            3 :     ZEND_PARSE_PARAMETERS_NONE();
     447              : 
     448            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     449            2 :     RETURN_BOOL(pango_layout_get_justify(layout_object->layout));
     450              : }
     451              : /* }}} */
     452              : 
     453              : /* {{{ Sets whether each line should be justified. */
     454            4 : PHP_METHOD(Pango_Layout, setAlignment)
     455              : {
     456              :     pango_layout_object *layout_object;
     457              :     zend_object *alignment;
     458              : 
     459            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     460            4 :         Z_PARAM_OBJ_OF_CLASS(alignment, pango_ce_pango_alignment)
     461            4 :     ZEND_PARSE_PARAMETERS_END();
     462              : 
     463            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     464            1 :     pango_layout_set_alignment(
     465              :         layout_object->layout,
     466            2 :         Z_LVAL_P(zend_enum_fetch_case_value(alignment))
     467              :     );
     468              : }
     469              : /* }}} */
     470              : 
     471              : /* {{{ Returns whether text will be justified or not in the current layout */
     472            4 : PHP_METHOD(Pango_Layout, getAlignment)
     473              : {
     474              :     pango_layout_object *layout_object;
     475              :     zend_object *alignment_case;
     476              : 
     477            4 :     ZEND_PARSE_PARAMETERS_NONE();
     478              : 
     479            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     480              : 
     481            3 :     zend_enum_get_case_by_value(
     482              :         &alignment_case, pango_ce_pango_alignment,
     483            3 :         pango_layout_get_alignment(layout_object->layout),
     484              :         NULL, false
     485              :     );
     486              : 
     487            6 :     RETURN_OBJ_COPY(alignment_case);
     488              : }
     489              : /* }}} */
     490              : 
     491              : /* {{{ Sets how each line should be wrapped. */
     492            4 : PHP_METHOD(Pango_Layout, setWrap)
     493              : {
     494              :     pango_layout_object *layout_object;
     495              :     zend_object *wrap;
     496              : 
     497            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     498            4 :         Z_PARAM_OBJ_OF_CLASS(wrap, pango_ce_pango_wrap_mode)
     499            4 :     ZEND_PARSE_PARAMETERS_END();
     500              : 
     501            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     502            1 :     pango_layout_set_wrap(
     503              :         layout_object->layout,
     504            2 :         Z_LVAL_P(zend_enum_fetch_case_value(wrap))
     505              :     );
     506              : }
     507              : /* }}} */
     508              : 
     509              : /* {{{ Returns how text will be wrapped or not in the current layout. */
     510            4 : PHP_METHOD(Pango_Layout, getWrap)
     511              : {
     512              :     pango_layout_object *layout_object;
     513              :     zend_object *wrap_case;
     514              : 
     515            4 :     ZEND_PARSE_PARAMETERS_NONE();
     516              : 
     517            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     518            3 :     zend_enum_get_case_by_value(
     519              :         &wrap_case, pango_ce_pango_wrap_mode,
     520            3 :         pango_layout_get_wrap(layout_object->layout),
     521              :         NULL, false
     522              :     );
     523              : 
     524            6 :     RETURN_OBJ_COPY(wrap_case);
     525              : }
     526              : /* }}} */
     527              : 
     528              : /* {{{ Queries whether the layout had to wrap any paragraphs. */
     529            2 : PHP_METHOD(Pango_Layout, isWrapped)
     530              : {
     531              :     pango_layout_object *layout_object;
     532              : 
     533            2 :     ZEND_PARSE_PARAMETERS_NONE();
     534              : 
     535            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     536            1 :     RETURN_BOOL(pango_layout_is_wrapped(layout_object->layout));
     537              : }
     538              : /* }}} */
     539              : 
     540              : /* {{{ Sets how far each paragraph should be indented. */
     541            5 : PHP_METHOD(Pango_Layout, setIndent)
     542              : {
     543              :     pango_layout_object *layout_object;
     544              :     long indent;
     545              : 
     546            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     547            6 :         Z_PARAM_LONG(indent)
     548            5 :     ZEND_PARSE_PARAMETERS_END();
     549              : 
     550            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     551            2 :     pango_layout_set_indent(layout_object->layout, indent);
     552              : }
     553              : /* }}} */
     554              : 
     555              : /* {{{ Returns how text will be indented or not in the current layout */
     556            5 : PHP_METHOD(Pango_Layout, getIndent)
     557              : {
     558              :     pango_layout_object *layout_object;
     559              : 
     560            5 :     ZEND_PARSE_PARAMETERS_NONE();
     561              : 
     562            8 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     563            4 :     RETURN_LONG(pango_layout_get_indent(layout_object->layout));
     564              : }
     565              : /* }}} */
     566              : 
     567              : /* {{{ Sets the line spacing for the paragraph */
     568            4 : PHP_METHOD(Pango_Layout, setSpacing)
     569              : {
     570              :     pango_layout_object *layout_object;
     571              :     long spacing;
     572              : 
     573            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     574            4 :         Z_PARAM_LONG(spacing)
     575            4 :     ZEND_PARSE_PARAMETERS_END();
     576              : 
     577            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     578            1 :     pango_layout_set_spacing(layout_object->layout, spacing);
     579              : }
     580              : /* }}} */
     581              : 
     582              : /* {{{ Returns the spacing for the current layout */
     583            4 : PHP_METHOD(Pango_Layout, getSpacing)
     584              : {
     585              :     pango_layout_object *layout_object;
     586              : 
     587            4 :     ZEND_PARSE_PARAMETERS_NONE();
     588              : 
     589            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     590            3 :     RETURN_LONG(pango_layout_get_spacing(layout_object->layout));
     591              : }
     592              : /* }}} */
     593              : 
     594              : /* {{{ Sets the ellipsize mode for the layout */
     595            4 : PHP_METHOD(Pango_Layout, setEllipsize)
     596              : {
     597              :     pango_layout_object *layout_object;
     598              :     zend_object *ellipsize;
     599              : 
     600            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     601            4 :         Z_PARAM_OBJ_OF_CLASS(ellipsize, pango_ce_pango_ellipsize_mode)
     602            4 :     ZEND_PARSE_PARAMETERS_END();
     603              : 
     604            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     605            1 :     pango_layout_set_ellipsize(
     606              :         layout_object->layout,
     607            2 :         Z_LVAL_P(zend_enum_fetch_case_value(ellipsize))
     608              :     );
     609              : }
     610              : /* }}} */
     611              : 
     612              : /* {{{ Returns the ellipsize for the current layout */
     613            4 : PHP_METHOD(Pango_Layout, getEllipsize)
     614              : {
     615              :     pango_layout_object *layout_object;
     616              :     zend_object *ellipsize_case;
     617              : 
     618            4 :     ZEND_PARSE_PARAMETERS_NONE();
     619              : 
     620            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     621            3 :     zend_enum_get_case_by_value(
     622              :         &ellipsize_case, pango_ce_pango_ellipsize_mode,
     623            3 :         pango_layout_get_ellipsize(layout_object->layout),
     624              :         NULL, false
     625              :     );
     626              : 
     627            6 :     RETURN_OBJ_COPY(ellipsize_case);
     628              : }
     629              : /* }}} */
     630              : 
     631              : /* {{{ Queries whether the layout had to ellipsize any paragraphs */
     632            2 : PHP_METHOD(Pango_Layout, isEllipsized)
     633              : {
     634              :     pango_layout_object *layout_object;
     635              : 
     636            2 :     ZEND_PARSE_PARAMETERS_NONE();
     637              : 
     638            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     639            1 :     RETURN_BOOL(pango_layout_is_ellipsized(layout_object->layout));
     640              : }
     641              : /* }}} */
     642              : 
     643              : /* {{{ Returns an array of LayoutLines representing each line of the layout */
     644            6 : PHP_METHOD(Pango_Layout, getLines)
     645              : {
     646              :     zval *layout;
     647              :     pango_layout_object *layout_object;
     648              :     GSList *lines;
     649              :     GSList *iter;
     650              :     zval line_zv;
     651              :     pango_layout_line_object *line_object;
     652              : 
     653            6 :     ZEND_PARSE_PARAMETERS_NONE();
     654              : 
     655           10 :     layout = getThis();
     656            5 :     layout_object = Z_PANGO_LAYOUT_P(layout);
     657              :     // Todo: Check if there is always be at least one line, even for empty text
     658            5 :     if (!(lines = pango_layout_get_lines(layout_object->layout))) {
     659            0 :         RETURN_EMPTY_ARRAY();
     660              :     }
     661              : 
     662            5 :     array_init(return_value);
     663           20 :     for (iter = lines; iter != NULL; iter = iter->next) {
     664           15 :         object_init_ex(&line_zv, php_pango_get_layout_line_ce());
     665           15 :         line_object = Z_PANGO_LAYOUT_LINE_P(&line_zv);
     666           15 :         line_object->line = pango_layout_line_ref((PangoLayoutLine *)iter->data);
     667           15 :         ZVAL_COPY(&line_object->layout_zval, layout);
     668              : 
     669              :         add_next_index_zval(return_value, &line_zv);
     670              :     }
     671              : }
     672              : /* }}} */
     673              : 
     674              : /* {{{ Returns an array of LayoutLines representing each line of the layout */
     675           11 : PHP_METHOD(Pango_Layout, getLinesReadonly)
     676              : {
     677              :     zval *layout;
     678              :     pango_layout_object *layout_object;
     679              :     GSList *lines;
     680              :     GSList *iter;
     681              :     zval line_zv;
     682              :     pango_layout_line_object *line_object;
     683              : 
     684           11 :     ZEND_PARSE_PARAMETERS_NONE();
     685              : 
     686           20 :     layout = getThis();
     687           10 :     layout_object = Z_PANGO_LAYOUT_P(layout);
     688              :     // Todo: Check if there is always be at least one line, even for empty text
     689           10 :     if (!(lines = pango_layout_get_lines_readonly(layout_object->layout))) {
     690            0 :         RETURN_EMPTY_ARRAY();
     691              :     }
     692              : 
     693           10 :     array_init(return_value);
     694           22 :     for (iter = lines; iter != NULL; iter = iter->next) {
     695           12 :         object_init_ex(&line_zv, php_pango_get_layout_line_ce());
     696           12 :         line_object = Z_PANGO_LAYOUT_LINE_P(&line_zv);
     697           12 :         line_object->line = pango_layout_line_ref((PangoLayoutLine *)iter->data);
     698           12 :         ZVAL_COPY(&line_object->layout_zval, layout);
     699              : 
     700              :         add_next_index_zval(return_value, &line_zv);
     701              :     }
     702              : }
     703              : /* }}} */
     704              : 
     705              : /* {{{ Returns a particular LayoutLine from the layout */
     706            5 : PHP_METHOD(Pango_Layout, getLine)
     707              : {
     708              :     zval *layout;
     709              :     pango_layout_object *layout_object;
     710            5 :     zend_long line_number = 0;
     711              :     PangoLayoutLine *layout_line;
     712              :     pango_layout_line_object *layout_line_object;
     713              : 
     714            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     715            6 :         Z_PARAM_LONG(line_number)
     716            5 :     ZEND_PARSE_PARAMETERS_END();
     717              : 
     718            4 :     layout = getThis();
     719            2 :     layout_object = Z_PANGO_LAYOUT_P(layout);
     720              : 
     721            2 :     if (!(layout_line = pango_layout_get_line(layout_object->layout, (int) line_number))) {
     722            0 :         RETURN_NULL();
     723              :     }
     724              : 
     725            2 :     object_init_ex(return_value, php_pango_get_layout_line_ce());
     726            2 :     layout_line_object = Z_PANGO_LAYOUT_LINE_P(return_value);
     727            2 :     layout_line_object->line = pango_layout_line_ref(layout_line);
     728            2 :     ZVAL_COPY(&layout_line_object->layout_zval, layout);
     729              : }
     730              : 
     731              : /* {{{ Returns a particular LayoutLine from the layout */
     732           19 : PHP_METHOD(Pango_Layout, getLineReadonly)
     733              : {
     734              :     zval *layout;
     735              :     pango_layout_object *layout_object;
     736           19 :     zend_long line_number = 0;
     737              :     PangoLayoutLine *layout_line;
     738              :     pango_layout_line_object *layout_line_object;
     739              : 
     740           19 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     741           34 :         Z_PARAM_LONG(line_number)
     742           19 :     ZEND_PARSE_PARAMETERS_END();
     743              : 
     744           32 :     layout = getThis();
     745           16 :     layout_object = Z_PANGO_LAYOUT_P(layout);
     746              : 
     747           16 :     if (!(layout_line = pango_layout_get_line_readonly(layout_object->layout, (int) line_number))) {
     748            0 :         RETURN_NULL();
     749              :     }
     750              : 
     751           16 :     object_init_ex(return_value, php_pango_get_layout_line_ce());
     752           16 :     layout_line_object = Z_PANGO_LAYOUT_LINE_P(return_value);
     753           16 :     layout_line_object->line = pango_layout_line_ref(layout_line);
     754           16 :     ZVAL_COPY(&layout_line_object->layout_zval, layout);
     755              : }
     756              : 
     757              : /* {{{ Returns the number of LayoutLines in the layout */
     758            5 : PHP_METHOD(Pango_Layout, getLineCount)
     759              : {
     760            5 :     zval *elem = NULL;
     761              :     pango_layout_object *layout_object;
     762              :     pango_layout_line_object *layout_line_object;
     763              : 
     764            5 :     ZEND_PARSE_PARAMETERS_NONE();
     765              : 
     766            8 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     767            4 :     RETURN_LONG(pango_layout_get_line_count(layout_object->layout));
     768              : }
     769              : /* }}} */
     770              : 
     771              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 50, 0)
     772              : /* {{{ The intended use of this function is testing, benchmarking and debugging. The format is not meant as a permanent storage format. */
     773            4 : PHP_METHOD(Pango_Layout, serialize)
     774              : {
     775            4 :     zend_long flags = PANGO_LAYOUT_SERIALIZE_DEFAULT;
     776              :     pango_layout_object *layout_object;
     777              :     GBytes* serialized_layout;
     778              :     const char *text;
     779              : 
     780            4 :     ZEND_PARSE_PARAMETERS_START(0, 1);
     781            3 :         Z_PARAM_OPTIONAL
     782            5 :         Z_PARAM_LONG(flags)
     783            4 :     ZEND_PARSE_PARAMETERS_END();
     784              : 
     785            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     786            2 :     if (!layout_object->layout) {
     787            0 :         RETURN_NULL();
     788              :     }
     789            2 :     if (serialized_layout = pango_layout_serialize(layout_object->layout, flags)) {
     790            2 :         text = g_bytes_get_data(serialized_layout, NULL);
     791            4 :         RETURN_STRING(text);
     792              :     }
     793              : 
     794            0 :     RETURN_EMPTY_STRING();
     795              : }
     796              : /* }}} */
     797              : #endif
     798              : 
     799              : /* {{{ Gets the Y position of baseline of the first line in layout.*/
     800            2 : PHP_METHOD(Pango_Layout, getBaseline)
     801              : {
     802              :     pango_layout_object *layout_object;
     803              : 
     804            2 :     ZEND_PARSE_PARAMETERS_NONE();
     805              : 
     806            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     807            1 :     RETURN_LONG(pango_layout_get_baseline(layout_object->layout));
     808              : }
     809              : /* }}} */
     810              : 
     811              : /* {{{ Gets whether to calculate the base direction for the layout according to its contents. */
     812            4 : PHP_METHOD(Pango_Layout, getAutoDir)
     813              : {
     814              :     pango_layout_object *layout_object;
     815              : 
     816            4 :     ZEND_PARSE_PARAMETERS_NONE();
     817              : 
     818            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     819            3 :     RETURN_BOOL(pango_layout_get_auto_dir(layout_object->layout));
     820              : }
     821              : /* }}} */
     822              : 
     823              : /* {{{ Sets whether to calculate the base direction for the layout according to its contents. */
     824            5 : PHP_METHOD(Pango_Layout, setAutoDir)
     825              : {
     826              :     pango_layout_object *layout_object;
     827              :     bool auto_dir;
     828              : 
     829            5 :     ZEND_PARSE_PARAMETERS_START(1, 1);
     830            6 :         Z_PARAM_BOOL(auto_dir)
     831            5 :     ZEND_PARSE_PARAMETERS_END();
     832              : 
     833            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     834            2 :     pango_layout_set_auto_dir(layout_object->layout, auto_dir);
     835              : }
     836              : /* }}} */
     837              : 
     838              : /* {{{ */
     839            2 : PHP_METHOD(Pango_Layout, getCharacterCount)
     840              : {
     841              :     pango_layout_object *layout_object;
     842              : 
     843            2 :     ZEND_PARSE_PARAMETERS_NONE();
     844              : 
     845            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     846            1 :     RETURN_LONG(pango_layout_get_character_count(layout_object->layout));
     847              : }
     848              : /* }}} */
     849              : 
     850              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 46, 0)
     851              : /* {{{ Gets the text direction at the given character position in layout. */
     852            4 : PHP_METHOD(Pango_Layout, getDirection)
     853              : {
     854              :     pango_layout_object *layout_object;
     855              :     zend_long byte_index;
     856              :     zend_object *direction_case;
     857              : 
     858            4 :     ZEND_PARSE_PARAMETERS_START(1, 1);
     859            4 :         Z_PARAM_LONG(byte_index)
     860            4 :     ZEND_PARSE_PARAMETERS_END();
     861              : 
     862            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     863            1 :     zend_enum_get_case_by_value(
     864              :         &direction_case, php_pango_get_direction_ce(),
     865            1 :         pango_layout_get_direction(layout_object->layout, byte_index),
     866              :         NULL, false
     867              :     );
     868              : 
     869            2 :     RETURN_OBJ_COPY(direction_case);
     870              : }
     871              : /* }}} */
     872              : #endif
     873              : 
     874              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 50, 0)
     875              : /* {{{ Gets whether the last line should be stretched to fill the entire width of the layout. */
     876            4 : PHP_METHOD(Pango_Layout, getJustifyLastLine)
     877              : {
     878              :     pango_layout_object *layout_object;
     879              : 
     880            4 :     ZEND_PARSE_PARAMETERS_NONE();
     881              : 
     882            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     883            3 :     RETURN_BOOL(pango_layout_get_justify_last_line(layout_object->layout));
     884              : }
     885              : /* }}} */
     886              : #endif
     887              : 
     888              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 50, 0)
     889              : /* {{{ Sets whether the last line should be stretched to fill the entire width of the layout. */
     890            5 : PHP_METHOD(Pango_Layout, setJustifyLastLine)
     891              : {
     892              :     pango_layout_object *layout_object;
     893              :     bool justify_last_line;
     894              : 
     895            5 :     ZEND_PARSE_PARAMETERS_START(1, 1);
     896            6 :         Z_PARAM_BOOL(justify_last_line)
     897            5 :     ZEND_PARSE_PARAMETERS_END();
     898              : 
     899            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     900            2 :     pango_layout_set_justify_last_line(layout_object->layout, justify_last_line);
     901              : }
     902              : /* }}} */
     903              : #endif
     904              : 
     905              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 44, 0)
     906              : /* {{{ */
     907            3 : PHP_METHOD(Pango_Layout, getLineSpacing)
     908              : {
     909              :     pango_layout_object *layout_object;
     910              : 
     911            3 :     ZEND_PARSE_PARAMETERS_NONE();
     912              : 
     913            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     914            2 :     RETURN_DOUBLE(pango_layout_get_line_spacing(layout_object->layout));
     915              : }
     916              : /* }}} */
     917              : #endif
     918              : 
     919              : #if PANGO_VERSION >= PANGO_VERSION_ENCODE(1, 50, 0)
     920              : /* {{{ */
     921            4 : PHP_METHOD(Pango_Layout, setLineSpacing)
     922              : {
     923              :     pango_layout_object *layout_object;
     924              :     double factor;
     925              : 
     926            4 :     ZEND_PARSE_PARAMETERS_START(1, 1);
     927            4 :         Z_PARAM_DOUBLE(factor)
     928            4 :     ZEND_PARSE_PARAMETERS_END();
     929              : 
     930            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     931            1 :     pango_layout_set_line_spacing(layout_object->layout, factor);
     932              : }
     933              : /* }}} */
     934              : #endif
     935              : 
     936              : /* {{{ */
     937            2 : PHP_METHOD(Pango_Layout, getUnknownGlyphsCount)
     938              : {
     939              :     pango_layout_object *layout_object;
     940              : 
     941            2 :     ZEND_PARSE_PARAMETERS_NONE();
     942              : 
     943            2 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     944            1 :     RETURN_LONG(pango_layout_get_unknown_glyphs_count(layout_object->layout));
     945              : }
     946              : /* }}} */
     947              : 
     948              : /* {{{ Obtains whether layout is in single paragraph mode. */
     949            4 : PHP_METHOD(Pango_Layout, getSingleParagraphMode)
     950              : {
     951              :     pango_layout_object *layout_object;
     952              : 
     953            4 :     ZEND_PARSE_PARAMETERS_NONE();
     954              : 
     955            6 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     956            3 :     RETURN_BOOL(pango_layout_get_single_paragraph_mode(layout_object->layout));
     957              : }
     958              : /* }}} */
     959              : 
     960              : 
     961              : /* {{{ Sets the single paragraph mode. */
     962            5 : PHP_METHOD(Pango_Layout, setSingleParagraphMode)
     963              : {
     964              :     pango_layout_object *layout_object;
     965              :     bool setting;
     966              : 
     967            5 :     ZEND_PARSE_PARAMETERS_START(1, 1);
     968            6 :         Z_PARAM_BOOL(setting)
     969            5 :     ZEND_PARSE_PARAMETERS_END();
     970              : 
     971            4 :     layout_object = Z_PANGO_LAYOUT_P(getThis());
     972            2 :     pango_layout_set_single_paragraph_mode(layout_object->layout, setting);
     973              : }
     974              : /* }}} */
     975              : 
     976              : 
     977              : /* ----------------------------------------------------------------
     978              :     \Pango\Layout Object management
     979              : ------------------------------------------------------------------*/
     980              : 
     981              : /* {{{ */
     982           60 : static void pango_layout_free_obj(zend_object *zobj)
     983              : {
     984           60 :     pango_layout_object *intern = pango_layout_fetch_object(zobj);
     985              : 
     986           60 :     if (!intern) {
     987            0 :         return;
     988              :     }
     989              : 
     990           60 :     if (intern->layout) {
     991           57 :         g_object_unref(intern->layout);
     992              :     }
     993              : 
     994           60 :     zval_ptr_dtor(&intern->pango_context_zv);
     995           60 :     zval_ptr_dtor(&intern->cairo_context_zv);
     996              : 
     997           60 :     zend_object_std_dtor(&intern->std);
     998              : }
     999              : /* }}} */
    1000              : 
    1001              : /* {{{ */
    1002           60 : static zend_object* pango_layout_obj_ctor(zend_class_entry *ce, pango_layout_object **intern)
    1003              : {
    1004           60 :     pango_layout_object *object = ecalloc(1, sizeof(pango_layout_object) + zend_object_properties_size(ce));
    1005              : 
    1006           60 :     ZVAL_UNDEF(&object->cairo_context_zv);
    1007           60 :     ZVAL_UNDEF(&object->pango_context_zv);
    1008              : 
    1009           60 :     zend_object_std_init(&object->std, ce);
    1010              : 
    1011           60 :     object->std.handlers = &pango_layout_object_handlers;
    1012           60 :     *intern = object;
    1013              : 
    1014           60 :     return &object->std;
    1015              : }
    1016              : /* }}} */
    1017              : 
    1018              : /* {{{ */
    1019           60 : static zend_object* pango_layout_create_object(zend_class_entry *ce)
    1020              : {
    1021           60 :     pango_layout_object *intern = NULL;
    1022           60 :     zend_object *return_value = pango_layout_obj_ctor(ce, &intern);
    1023              : 
    1024           60 :     object_properties_init(&intern->std, ce);
    1025           60 :     return return_value;
    1026              : }
    1027              : /* }}} */
    1028              : 
    1029              : /* {{{ PHP_MINIT_FUNCTION */
    1030          194 : PHP_MINIT_FUNCTION(pango_layout)
    1031              : {
    1032          194 :     memcpy(
    1033              :         &pango_layout_object_handlers,
    1034              :         zend_get_std_object_handlers(),
    1035              :         sizeof(zend_object_handlers)
    1036              :     );
    1037              : 
    1038          194 :     pango_layout_object_handlers.offset = XtOffsetOf(pango_layout_object, std);
    1039          194 :     pango_layout_object_handlers.free_obj = pango_layout_free_obj;
    1040              : 
    1041          194 :     pango_ce_pango_layout = register_class_Pango_Layout();
    1042          194 :     pango_ce_pango_layout->create_object = pango_layout_create_object;
    1043              : 
    1044          194 :     pango_ce_pango_alignment = register_class_Pango_Alignment();
    1045          194 :     pango_ce_pango_wrap_mode = register_class_Pango_WrapMode();
    1046          194 :     pango_ce_pango_ellipsize_mode = register_class_Pango_EllipsizeMode();
    1047              : 
    1048          194 :     return SUCCESS;
    1049              : }
    1050              : /* }}} */
        

Generated by: LCOV version 2.0-1