From f41932c5c5155a1ac3bedebdceb95603de95c919 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 5 Jul 2019 20:56:02 -0400 Subject: Support size as percentage in markup Test included. Closes https://gitlab.gnome.org/GNOME/pango/issues/23 --- docs/pango_markup.sgml | 3 +- pango/pango-attributes.c | 10 +++--- pango/pango-markup.c | 76 ++++++++++++++++++++++++++++++----------- tests/markups/valid-12.expected | 20 +++++++++++ tests/markups/valid-12.markup | 1 + 5 files changed, 84 insertions(+), 26 deletions(-) create mode 100644 tests/markups/valid-12.expected create mode 100644 tests/markups/valid-12.markup diff --git a/docs/pango_markup.sgml b/docs/pango_markup.sgml index c2ba377c..8bbdaad8 100644 --- a/docs/pango_markup.sgml +++ b/docs/pango_markup.sgml @@ -79,7 +79,8 @@ A font family name Font size in 1024ths of a point, or one of the absolute sizes 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', -'xx-large', or one of the relative sizes 'smaller' or 'larger'. +'xx-large', or one of the relative sizes 'smaller' or 'larger', +or a percentage like '150%'. If you want to specify a absolute size, it's usually easier to take advantage of the ability to specify a partial font description using 'font'; you can use diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c index 85e5a240..af4289ee 100644 --- a/pango/pango-attributes.c +++ b/pango/pango-attributes.c @@ -1901,8 +1901,7 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, PangoFontMask mask = 0; gboolean have_language = FALSE; - gdouble scale = 0; - gboolean have_scale = FALSE; + double scale = 1.0; g_return_if_fail (iterator != NULL); g_return_if_fail (desc != NULL); @@ -1980,10 +1979,9 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, } break; case PANGO_ATTR_SCALE: - if (!have_scale) + if (!(mask & PANGO_FONT_MASK_SIZE)) { - have_scale = TRUE; - scale = ((PangoAttrFloat *)attr)->value; + scale *= ((PangoAttrFloat *)attr)->value; } break; case PANGO_ATTR_LANGUAGE: @@ -2024,7 +2022,7 @@ pango_attr_iterator_get_font (PangoAttrIterator *iterator, } } - if (have_scale) + if (scale != 1.0) { if (pango_font_description_get_size_is_absolute (desc)) pango_font_description_set_absolute_size (desc, scale * pango_font_description_get_size (desc)); diff --git a/pango/pango-markup.c b/pango/pango-markup.c index 7420fa85..2d24eda3 100644 --- a/pango/pango-markup.c +++ b/pango/pango-markup.c @@ -64,15 +64,19 @@ struct _OpenTag { GSList *attrs; gsize start_index; + /* Our impact on scale_factor, so we know whether we + * need to create an attribute ourselves on close + */ + gboolean has_scale; /* Current total scale level; reset whenever * an absolute size is set. * Each "larger" ups it 1, each "smaller" decrements it 1 */ gint scale_level; - /* Our impact on scale_level, so we know whether we - * need to create an attribute ourselves on close + /* Current scale factor; reset whenever + * an absolute size is set. */ - gint scale_level_delta; + gint scale_factor; /* Base scale factor currently in effect * or size that this tag * forces, or parent's scale factor or size. @@ -203,7 +207,8 @@ open_tag_set_absolute_font_size (OpenTag *ot, ot->base_font_size = font_size; ot->has_base_font_size = TRUE; ot->scale_level = 0; - ot->scale_level_delta = 0; + ot->scale_factor = 1.0; + ot->has_scale = FALSE; } static void @@ -213,7 +218,8 @@ open_tag_set_absolute_font_scale (OpenTag *ot, ot->base_scale_factor = scale; ot->has_base_font_size = FALSE; ot->scale_level = 0; - ot->scale_level_delta = 0; + ot->scale_factor = 1.0; + ot->has_scale = FALSE; } static OpenTag* @@ -231,7 +237,7 @@ markup_data_open_tag (MarkupData *md) ot = g_slice_new (OpenTag); ot->attrs = NULL; ot->start_index = md->index; - ot->scale_level_delta = 0; + ot->has_scale = FALSE; if (parent == NULL) { @@ -239,6 +245,7 @@ markup_data_open_tag (MarkupData *md) ot->base_font_size = 0; ot->has_base_font_size = FALSE; ot->scale_level = 0; + ot->scale_factor = 1.0; } else { @@ -246,6 +253,7 @@ markup_data_open_tag (MarkupData *md) ot->base_font_size = parent->base_font_size; ot->has_base_font_size = parent->has_base_font_size; ot->scale_level = parent->scale_level; + ot->scale_factor = parent->scale_factor; } md->tag_stack = g_slist_prepend (md->tag_stack, ot); @@ -285,7 +293,7 @@ markup_data_close_tag (MarkupData *md) tmp_list = g_slist_next (tmp_list); } - if (ot->scale_level_delta != 0) + if (ot->has_scale) { /* We affected relative font size; create an appropriate * attribute and reverse our effects on the current level @@ -298,7 +306,7 @@ markup_data_close_tag (MarkupData *md) * as the base size to be scaled from */ a = pango_attr_size_new (scale_factor (ot->scale_level, - 1.0) * + ot->scale_factor) * ot->base_font_size); } else @@ -307,7 +315,8 @@ markup_data_close_tag (MarkupData *md) * as the base size to be scaled from */ a = pango_attr_scale_new (scale_factor (ot->scale_level, - ot->base_scale_factor)); + ot->scale_factor * + ot->base_scale_factor)); } a->start_index = ot->start_index; @@ -870,7 +879,7 @@ big_parse_func (MarkupData *md G_GNUC_UNUSED, /* Grow text one level */ if (tag) { - tag->scale_level_delta += 1; + tag->has_scale = TRUE; tag->scale_level += 1; } @@ -1257,27 +1266,56 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, const char *end; gint n; - if ((end = size, !_pango_scan_int (&end, &n)) || *end != '\0' || n < 0) + end = size; + + if (_pango_scan_int (&end, &n) && n > 0) + { + if (*end == '\0') + { + add_attribute (tag, pango_attr_size_new (n)); + if (tag) + open_tag_set_absolute_font_size (tag, n); + } + else if (*end == '%' && *(end + 1) == '\0') + { + if (tag) + { + tag->has_scale = TRUE; + tag->base_scale_factor = ((double)n) / 100; + } + } + else + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + _("Value of 'size' attribute on tag on line %d " + "could not be parsed; should be an integer no more than %d," + " a percentage, " + " or a string such as 'small', not '%s'"), + line_number, INT_MAX, size); + goto error; + } + } + else { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Value of 'size' attribute on tag on line %d " "could not be parsed; should be an integer no more than %d," + " a percentage," " or a string such as 'small', not '%s'"), line_number, INT_MAX, size); goto error; } - add_attribute (tag, pango_attr_size_new (n)); - if (tag) - open_tag_set_absolute_font_size (tag, n); } else if (strcmp (size, "smaller") == 0) { if (tag) { - tag->scale_level_delta -= 1; + tag->has_scale = TRUE; tag->scale_level -= 1; } } @@ -1285,7 +1323,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED, { if (tag) { - tag->scale_level_delta += 1; + tag->has_scale = TRUE; tag->scale_level += 1; } } @@ -1605,7 +1643,7 @@ sub_parse_func (MarkupData *md G_GNUC_UNUSED, /* Shrink font, and set a negative rise */ if (tag) { - tag->scale_level_delta -= 1; + tag->has_scale = TRUE; tag->scale_level -= 1; } @@ -1627,7 +1665,7 @@ sup_parse_func (MarkupData *md G_GNUC_UNUSED, /* Shrink font, and set a positive rise */ if (tag) { - tag->scale_level_delta -= 1; + tag->has_scale = TRUE; tag->scale_level -= 1; } @@ -1649,7 +1687,7 @@ small_parse_func (MarkupData *md G_GNUC_UNUSED, /* Shrink text one level */ if (tag) { - tag->scale_level_delta -= 1; + tag->has_scale = TRUE; tag->scale_level -= 1; } diff --git a/tests/markups/valid-12.expected b/tests/markups/valid-12.expected new file mode 100644 index 00000000..83239d1e --- /dev/null +++ b/tests/markups/valid-12.expected @@ -0,0 +1,20 @@ +Blue text is cool! + + +--- + +range 0 9 +[0 9] scale 2.000000 +[0 9] foreground #00000000ffff +range 9 13 +range 13 17 +[13 17] style 2 +range 17 2147483647 + + +--- + +[0:9] (null) Normal 0 +[9:13] (null) Normal 0 +[13:17] (null) Italic 0 +[17:2147483647] (null) Italic 0 diff --git a/tests/markups/valid-12.markup b/tests/markups/valid-12.markup new file mode 100644 index 00000000..9a95ec32 --- /dev/null +++ b/tests/markups/valid-12.markup @@ -0,0 +1 @@ +Blue text is cool! -- cgit v1.2.1