summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2021-10-31 01:50:21 +0000
committerMatthias Clasen <mclasen@redhat.com>2021-10-31 01:50:21 +0000
commit7c710faa1edd58109c4ac1972ae5aca10f1be87f (patch)
tree4abd52c5ccda75dea45d82965b5d244dfd868ab7
parentf33cbe522dbb5ccfff9e70ef108061813ed61cb8 (diff)
parentab776f328ba3540f6607ea0a9bc72a57b607b9ac (diff)
downloadpango-7c710faa1edd58109c4ac1972ae5aca10f1be87f.tar.gz
Merge branch 'glyph-extents-fixes' into 'main'
cairo: Produce meaningful logical glyph extents See merge request GNOME/pango!490
-rw-r--r--pango/pangocairo-fcfont.c7
-rw-r--r--pango/pangocairo-font.c86
-rw-r--r--tests/testmisc.c56
3 files changed, 113 insertions, 36 deletions
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 85cc45c8..4453b5ab 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -75,14 +75,13 @@ static PangoFontMetrics *
pango_cairo_fc_font_create_base_metrics_for_context (PangoCairoFont *cfont,
PangoContext *context)
{
- PangoFcFont *fcfont = (PangoFcFont *) (cfont);
+ PangoCairoFcFont *cffont = (PangoCairoFcFont *) cfont;
+ PangoFcFont *fcfont = (PangoFcFont *) cfont;
PangoFontMetrics *metrics;
- const cairo_font_options_t *options;
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)
+ if (_pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv))
{
metrics->ascent = PANGO_PIXELS_CEIL (metrics->ascent) * PANGO_SCALE;
metrics->descent = PANGO_PIXELS_CEIL (metrics->descent) * PANGO_SCALE;
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 69c375c3..503f863b 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -693,7 +693,7 @@ get_space_extents (PangoCairoFontPrivate *cf_priv,
cairo_text_extents_t extents;
c[0] = hexdigits[i];
- cairo_scaled_font_text_extents (cf_priv->scaled_font, c, &extents);
+ cairo_scaled_font_text_extents (_pango_cairo_font_private_get_scaled_font (cf_priv), c, &extents);
hex_width += extents.width;
}
width = pango_units_from_double (hex_width / 16);
@@ -784,40 +784,60 @@ 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;
+ hb_font_extents_t extents;
- cairo_scaled_font_extents (scaled_font, &font_extents);
+ hb_font_get_h_extents (pango_font_get_hb_font (PANGO_FONT (cf_priv->cfont)),
+ &extents);
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 = extents.ascender - extents.descender;
+
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 = - extents.ascender;
+ break;
case PANGO_GRAVITY_NORTH:
- cf_priv->font_extents.y = - pango_units_from_double (font_extents.descent);
- break;
+ cf_priv->font_extents.y = extents.descender;
+ 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 = cf_priv->font_extents.height / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ cf_priv->font_extents.y = - ascent;
+ }
+ break;
}
- 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 */
+ if (cf_priv->is_hinted)
+ {
+ if (cf_priv->font_extents.y < 0)
+ cf_priv->font_extents.y = PANGO_UNITS_ROUND (cf_priv->font_extents.y - PANGO_SCALE/2);
+ else
+ cf_priv->font_extents.y = PANGO_UNITS_ROUND (cf_priv->font_extents.y + PANGO_SCALE/2);
+ if (cf_priv->font_extents.height < 0)
+ cf_priv->font_extents.height = PANGO_UNITS_ROUND (cf_priv->font_extents.height - PANGO_SCALE/2);
+ else
+ cf_priv->font_extents.height = PANGO_UNITS_ROUND (cf_priv->font_extents.height + PANGO_SCALE/2);
+ }
+
+ if (PANGO_GRAVITY_IS_IMPROPER (cf_priv->gravity))
+ {
+ cf_priv->font_extents.y = - cf_priv->font_extents.y;
+ cf_priv->font_extents.height = - cf_priv->font_extents.height;
+ }
+
+ 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;
}
@@ -841,7 +861,10 @@ compute_glyph_extents (PangoCairoFontPrivate *cf_priv,
&cairo_glyph, 1, &extents);
entry->glyph = glyph;
- entry->width = pango_units_from_double (extents.x_advance);
+ if (PANGO_GRAVITY_IS_VERTICAL (cf_priv->gravity))
+ entry->width = pango_units_from_double (extents.y_advance);
+ else
+ entry->width = pango_units_from_double (extents.x_advance);
entry->ink_rect.x = pango_units_from_double (extents.x_bearing);
entry->ink_rect.y = pango_units_from_double (extents.y_bearing);
entry->ink_rect.width = pango_units_from_double (extents.width);
@@ -904,6 +927,23 @@ _pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
if (logical_rect)
{
*logical_rect = cf_priv->font_extents;
- logical_rect->width = entry->width;
+ switch (cf_priv->gravity)
+ {
+ case PANGO_GRAVITY_SOUTH:
+ logical_rect->width = entry->width;
+ break;
+ case PANGO_GRAVITY_EAST:
+ logical_rect->width = cf_priv->font_extents.height;
+ break;
+ case PANGO_GRAVITY_NORTH:
+ logical_rect->width = entry->width;
+ break;
+ case PANGO_GRAVITY_WEST:
+ logical_rect->width = - cf_priv->font_extents.height;
+ break;
+ case PANGO_GRAVITY_AUTO:
+ default:
+ g_assert_not_reached ();
+ }
}
}
diff --git a/tests/testmisc.c b/tests/testmisc.c
index 85a3b0b5..2e14f11e 100644
--- a/tests/testmisc.c
+++ b/tests/testmisc.c
@@ -125,9 +125,6 @@ test_line_height (void)
g_object_unref (context);
}
-#if 0
-/* These tests fail since I had to revert 20ec670e124e446107
- */
static void
test_line_height2 (void)
{
@@ -255,7 +252,6 @@ test_cursor_height2 (void)
g_object_unref (layout);
g_object_unref (context);
}
-#endif
static void
test_attr_list_update (void)
@@ -661,6 +657,47 @@ test_empty_line_height (void)
g_object_unref (context);
}
+static void
+test_gravity_metrics (void)
+{
+ PangoFontMap *map;
+ PangoContext *context;
+ PangoFontDescription *desc;
+ PangoFont *font;
+ PangoGlyph glyph;
+ PangoGravity gravity;
+ PangoRectangle ink[4];
+ PangoRectangle log[4];
+
+ map = pango_cairo_font_map_get_default ();
+ context = pango_font_map_create_context (map);
+
+ desc = pango_font_description_from_string ("Cantarell 64");
+
+ glyph = 1; /* A */
+
+ for (gravity = PANGO_GRAVITY_SOUTH; gravity <= PANGO_GRAVITY_WEST; gravity++)
+ {
+ pango_font_description_set_gravity (desc, gravity);
+ font = pango_font_map_load_font (map, context, desc);
+ pango_font_get_glyph_extents (font, glyph, &ink[gravity], &log[gravity]);
+ g_object_unref (font);
+ }
+
+ g_assert_cmpint (ink[PANGO_GRAVITY_EAST].width, ==, ink[PANGO_GRAVITY_SOUTH].height);
+ g_assert_cmpint (ink[PANGO_GRAVITY_EAST].height, ==, ink[PANGO_GRAVITY_SOUTH].width);
+ g_assert_cmpint (ink[PANGO_GRAVITY_NORTH].width, ==, ink[PANGO_GRAVITY_SOUTH].width);
+ g_assert_cmpint (ink[PANGO_GRAVITY_NORTH].height, ==, ink[PANGO_GRAVITY_SOUTH].height);
+ g_assert_cmpint (ink[PANGO_GRAVITY_WEST].width, ==, ink[PANGO_GRAVITY_SOUTH].height);
+ g_assert_cmpint (ink[PANGO_GRAVITY_WEST].height, ==, ink[PANGO_GRAVITY_SOUTH].width);
+
+ g_assert_cmpint (log[PANGO_GRAVITY_SOUTH].width, ==, - log[PANGO_GRAVITY_NORTH].width);
+ g_assert_cmpint (log[PANGO_GRAVITY_EAST].width, ==, - log[PANGO_GRAVITY_WEST].width);
+
+ pango_font_description_free (desc);
+ g_object_unref (context);
+}
+
int
main (int argc, char *argv[])
{
@@ -672,11 +709,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 ("/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);
@@ -692,6 +729,7 @@ main (int argc, char *argv[])
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);
+ g_test_add_func ("/layout/gravity-metrics", test_gravity_metrics);
return g_test_run ();
}