diff options
-rw-r--r-- | pango/pango-layout.c | 68 | ||||
-rw-r--r-- | pango/pangocairo-fcfont.c | 14 | ||||
-rw-r--r-- | pango/pangocairo-font.c | 43 | ||||
-rw-r--r-- | tests/testmisc.c | 174 |
4 files changed, 260 insertions, 39 deletions
diff --git a/pango/pango-layout.c b/pango/pango-layout.c index 74799ddc..6e761f2c 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -193,6 +193,7 @@ static void pango_layout_get_item_properties (PangoItem *item, static void pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, int index, PangoRectangle *logical_rect, + gboolean apply_line_height, int *height); static void pango_layout_finalize (GObject *object); @@ -1908,17 +1909,15 @@ pango_layout_index_to_line_and_extents (PangoLayout *layout, { if (run_rect) { - *run_rect = *line_rect; - while (TRUE) { PangoLayoutRun *run = _pango_layout_iter_get_run (&iter); - if (!run) - break; - pango_layout_iter_get_run_extents (&iter, NULL, run_rect); + if (!run) + break; + if (run->item->offset <= index && index < run->item->offset + run->item->length) break; @@ -4482,7 +4481,7 @@ pango_layout_check_lines (PangoLayout *layout) { PangoRectangle logical = { 0, }; int height = 0; - pango_layout_get_empty_extents_and_height_at_index (layout, 0, &logical, &height); + pango_layout_get_empty_extents_and_height_at_index (layout, 0, &logical, TRUE, &height); state.line_height = layout->line_spacing == 0.0 ? logical.height : layout->line_spacing * height; } @@ -5115,6 +5114,7 @@ static void pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, int index, PangoRectangle *logical_rect, + gboolean apply_line_height, int *height) { if (logical_rect) @@ -5122,6 +5122,8 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, PangoFont *font; PangoFontDescription *font_desc = NULL; gboolean free_font_desc = FALSE; + double line_height_factor = 0.0; + int absolute_line_height = 0; font_desc = pango_context_get_font_description (layout->context); @@ -5147,6 +5149,8 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, if (start <= index && index < end) { + PangoAttribute *attr; + if (!free_font_desc) { font_desc = pango_font_description_copy_static (font_desc); @@ -5158,6 +5162,14 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, NULL, NULL); + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_LINE_HEIGHT); + if (attr) + line_height_factor = ((PangoAttrFloat *)attr)->value; + + attr = pango_attr_iterator_get (&iter, PANGO_ATTR_ABSOLUTE_LINE_HEIGHT); + if (attr) + absolute_line_height = ((PangoAttrInt *)attr)->value; + break; } @@ -5183,6 +5195,18 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, *height = pango_font_metrics_get_height (metrics); pango_font_metrics_unref (metrics); + + if (apply_line_height && + (absolute_line_height != 0 || line_height_factor != 0.0)) + { + int line_height, leading; + + line_height = MAX (absolute_line_height, ceilf (line_height_factor * logical_rect->height)); + + leading = line_height - logical_rect->height; + logical_rect->y -= leading / 2; + logical_rect->height += leading; + } } else { @@ -5206,14 +5230,6 @@ pango_layout_get_empty_extents_and_height_at_index (PangoLayout *layout, } static void -pango_layout_line_get_empty_extents_and_height (PangoLayoutLine *line, - PangoRectangle *logical_rect, - int *height) -{ - pango_layout_get_empty_extents_and_height_at_index (line->layout, line->start_index, logical_rect, height); -} - -static void pango_layout_run_get_extents_and_height (PangoLayoutRun *run, PangoRectangle *run_ink, PangoRectangle *run_logical, @@ -5347,6 +5363,7 @@ pango_layout_run_get_extents_and_height (PangoLayoutRun *run, int line_height, leading; line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * line_logical->height)); + leading = line_height - line_logical->height; line_logical->y -= leading / 2; line_logical->height += leading; @@ -5479,7 +5496,7 @@ pango_layout_line_get_extents_and_height (PangoLayoutLine *line, PangoRectangle r, *rect; rect = logical_rect ? logical_rect : &r; - pango_layout_line_get_empty_extents_and_height (line, rect, height); + pango_layout_get_empty_extents_and_height_at_index (line->layout, line->start_index, rect, TRUE, height); } if (caching) @@ -7341,18 +7358,35 @@ pango_layout_iter_get_run_extents (PangoLayoutIter *iter, } else { - /* The empty run at the end of a line */ + if (iter->line->runs) + { + /* The empty run at the end of a non-empty line */ + PangoLayoutRun *run = g_slist_last (iter->line->runs)->data; + pango_layout_run_get_extents_and_height (run, ink_rect, logical_rect, NULL, NULL); + } + else + { + PangoRectangle r; - pango_layout_iter_get_line_extents (iter, ink_rect, logical_rect); + pango_layout_get_empty_extents_and_height_at_index (iter->layout, 0, &r, FALSE, NULL); + + if (ink_rect) + *ink_rect = r; + + if (logical_rect) + *logical_rect = r; + } if (ink_rect) { + offset_y (iter, &ink_rect->y); ink_rect->x = iter->run_x; ink_rect->width = 0; } if (logical_rect) { + offset_y (iter, &logical_rect->y); logical_rect->x = iter->run_x; logical_rect->width = 0; } diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c index 0019f83a..85cc45c8 100644 --- a/pango/pangocairo-fcfont.c +++ b/pango/pangocairo-fcfont.c @@ -76,8 +76,20 @@ pango_cairo_fc_font_create_base_metrics_for_context (PangoCairoFont *cfont, PangoContext *context) { PangoFcFont *fcfont = (PangoFcFont *) (cfont); + PangoFontMetrics *metrics; + const cairo_font_options_t *options; - return pango_fc_font_create_base_metrics_for_context (fcfont, context); + metrics = pango_fc_font_create_base_metrics_for_context (fcfont, context); + + options = pango_cairo_context_get_font_options (context); + if (cairo_font_options_get_hint_metrics (options) == CAIRO_HINT_METRICS_ON) + { + metrics->ascent = PANGO_PIXELS_CEIL (metrics->ascent) * PANGO_SCALE; + metrics->descent = PANGO_PIXELS_CEIL (metrics->descent) * PANGO_SCALE; + metrics->height = PANGO_PIXELS_CEIL (metrics->height) * PANGO_SCALE; + } + + return metrics; } static void diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c index 69c375c3..15c5be4a 100644 --- a/pango/pangocairo-font.c +++ b/pango/pangocairo-font.c @@ -784,40 +784,41 @@ struct _PangoCairoFontGlyphExtentsCacheEntry static gboolean _pango_cairo_font_private_glyph_extents_cache_init (PangoCairoFontPrivate *cf_priv) { - cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv); - cairo_font_extents_t font_extents; - - if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS)) - return FALSE; - - cairo_scaled_font_extents (scaled_font, &font_extents); + PangoCairoFont *cfont = cf_priv->cfont; + PangoFontMetrics *metrics = _pango_cairo_font_get_metrics (PANGO_FONT (cfont), NULL); cf_priv->font_extents.x = 0; cf_priv->font_extents.width = 0; - cf_priv->font_extents.height = pango_units_from_double (font_extents.ascent + font_extents.descent); + cf_priv->font_extents.height = metrics->ascent + metrics->descent; + switch (cf_priv->gravity) { default: case PANGO_GRAVITY_AUTO: case PANGO_GRAVITY_SOUTH: - cf_priv->font_extents.y = - pango_units_from_double (font_extents.ascent); - break; + cf_priv->font_extents.y = - metrics->ascent; + break; case PANGO_GRAVITY_NORTH: - cf_priv->font_extents.y = - pango_units_from_double (font_extents.descent); - break; + cf_priv->font_extents.y = - metrics->descent; + break; case PANGO_GRAVITY_EAST: case PANGO_GRAVITY_WEST: - { - int ascent = pango_units_from_double (font_extents.ascent + font_extents.descent) / 2; - if (cf_priv->is_hinted) - ascent = PANGO_UNITS_ROUND (ascent); - cf_priv->font_extents.y = - ascent; - } + { + int ascent = (metrics->ascent + metrics->descent) / 2; + if (cf_priv->is_hinted) + ascent = PANGO_UNITS_ROUND (ascent); + cf_priv->font_extents.y = - ascent; + } } - cf_priv->glyph_extents_cache = g_new0 (PangoCairoFontGlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES); - /* Make sure all cache entries are invalid initially */ - cf_priv->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */ + pango_font_metrics_unref (metrics); + + if (!cf_priv->glyph_extents_cache) + { + cf_priv->glyph_extents_cache = g_new0 (PangoCairoFontGlyphExtentsCacheEntry, GLYPH_CACHE_NUM_ENTRIES); + /* Make sure all cache entries are invalid initially */ + cf_priv->glyph_extents_cache[0].glyph = 1; /* glyph 1 cannot happen in bucket 0 */ + } return TRUE; } diff --git a/tests/testmisc.c b/tests/testmisc.c index 60694134..b9ec81ea 100644 --- a/tests/testmisc.c +++ b/tests/testmisc.c @@ -126,6 +126,134 @@ test_line_height (void) } static void +test_line_height2 (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoLayoutLine *line; + int height1 = 0; + int height2 = 0; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "one", -1); + + line = pango_layout_get_line_readonly (layout, 0); + pango_layout_line_get_height (line, &height1); + + pango_layout_set_text (layout, "", -1); + + line = pango_layout_get_line_readonly (layout, 0); + pango_layout_line_get_height (line, &height2); + + g_assert_cmpint (height1, ==, height2); + + g_object_unref (layout); + g_object_unref (context); +} + +static void +test_line_height3 (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoLayoutLine *line; + PangoAttrList *attrs; + int height1 = 0; + int height2 = 0; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "one", -1); + attrs = pango_attr_list_new (); + pango_attr_list_insert (attrs, pango_attr_line_height_new (2.0)); + pango_layout_set_attributes (layout, attrs); + pango_attr_list_unref (attrs); + + line = pango_layout_get_line_readonly (layout, 0); + pango_layout_line_get_height (line, &height1); + + pango_layout_set_text (layout, "", -1); + + line = pango_layout_get_line_readonly (layout, 0); + pango_layout_line_get_height (line, &height2); + + g_assert_cmpint (height1, ==, height2); + + g_object_unref (layout); + g_object_unref (context); +} + +static void +test_run_height (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoLayoutIter *iter; + PangoRectangle logical1, logical2; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "one", -1); + + iter = pango_layout_get_iter (layout); + pango_layout_iter_get_run_extents (iter, NULL, &logical1); + pango_layout_iter_free (iter); + + pango_layout_set_text (layout, "", -1); + + iter = pango_layout_get_iter (layout); + pango_layout_iter_get_run_extents (iter, NULL, &logical2); + pango_layout_iter_free (iter); + + g_assert_cmpint (logical1.height, ==, logical2.height); + + g_object_unref (layout); + g_object_unref (context); +} + +static void +test_cursor_height (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoRectangle strong; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "one\ttwo", -1); + pango_layout_get_cursor_pos (layout, 0, &strong, NULL); + + g_assert_cmpint (strong.height, >, 0); + + g_object_unref (layout); + g_object_unref (context); +} + +static void +test_cursor_height2 (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoRectangle strong1, strong2; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + layout = pango_layout_new (context); + pango_layout_set_text (layout, "one", -1); + + pango_layout_get_cursor_pos (layout, 0, &strong1, NULL); + + pango_layout_set_text (layout, "", -1); + + pango_layout_get_cursor_pos (layout, 0, &strong2, NULL); + + g_assert_cmpint (strong1.height, ==, strong2.height); + + g_object_unref (layout); + g_object_unref (context); +} + +static void test_attr_list_update (void) { PangoAttribute *weight_attr; @@ -489,6 +617,46 @@ test_extents (void) g_object_unref (context); } +static void +test_empty_line_height (void) +{ + PangoContext *context; + PangoLayout *layout; + PangoRectangle ext1, ext2, ext3; + cairo_font_options_t *options; + int hint; + + context = pango_font_map_create_context (pango_cairo_font_map_get_default ()); + + for (hint = CAIRO_HINT_METRICS_OFF; hint <= CAIRO_HINT_METRICS_ON; hint++) + { + options = cairo_font_options_create (); + cairo_font_options_set_hint_metrics (options, hint); + pango_cairo_context_set_font_options (context, options); + cairo_font_options_destroy (options); + + layout = pango_layout_new (context); + + pango_layout_get_extents (layout, NULL, &ext1); + + pango_layout_set_text (layout, "a", 1); + + pango_layout_get_extents (layout, NULL, &ext2); + + g_assert_cmpint (ext1.height, ==, ext2.height); + + pango_layout_set_text (layout, "Pg", 1); + + pango_layout_get_extents (layout, NULL, &ext3); + + g_assert_cmpint (ext2.height, ==, ext3.height); + + g_object_unref (layout); + } + + g_object_unref (context); +} + int main (int argc, char *argv[]) { @@ -500,6 +668,11 @@ main (int argc, char *argv[]) g_test_add_func ("/layout/short-string-crash", test_short_string_crash); g_test_add_func ("/language/emoji-crash", test_language_emoji_crash); g_test_add_func ("/layout/line-height", test_line_height); + g_test_add_func ("/layout/line-height2", test_line_height2); + g_test_add_func ("/layout/line-height3", test_line_height3); + g_test_add_func ("/layout/run-height", test_run_height); + g_test_add_func ("/layout/cursor-height", test_cursor_height); + g_test_add_func ("/layout/cursor-height2", test_cursor_height2); g_test_add_func ("/attr-list/update", test_attr_list_update); g_test_add_func ("/misc/version-info", test_version_info); g_test_add_func ("/misc/is-zerowidth", test_is_zero_width); @@ -514,6 +687,7 @@ main (int argc, char *argv[]) g_test_add_func ("/bidi/get-cursor", test_get_cursor); g_test_add_func ("/layout/index-to-x", test_index_to_x); g_test_add_func ("/layout/extents", test_extents); + g_test_add_func ("/layout/empty-line-height", test_empty_line_height); return g_test_run (); } |