summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2019-08-14 18:15:34 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2019-08-14 18:16:27 +0200
commit1fe467589cbd6b407eabe6fbb8a8b2cd4beedc1b (patch)
tree956b910a7e3dc5f4a7494073e7d65e5ce8e2a980
parentcb3e2aafeb090fd17f0fdfba23d0e4228e76167c (diff)
downloadpango-1fe467589cbd6b407eabe6fbb8a8b2cd4beedc1b.tar.gz
Revert "Drop cairo metrics implementation"
This reverts commit c5d86c368128bb9a0be913829da79649fb81f486. Closes #409
-rw-r--r--pango/pangocairo-coretextfont.c1
-rw-r--r--pango/pangocairo-fcfont.c1
-rw-r--r--pango/pangocairo-font.c194
-rw-r--r--pango/pangocairo-private.h2
-rw-r--r--pango/pangocairo-win32font.c1
5 files changed, 199 insertions, 0 deletions
diff --git a/pango/pangocairo-coretextfont.c b/pango/pangocairo-coretextfont.c
index 165e0924..fa9f383a 100644
--- a/pango/pangocairo-coretextfont.c
+++ b/pango/pangocairo-coretextfont.c
@@ -156,6 +156,7 @@ pango_cairo_core_text_font_class_init (PangoCairoCoreTextFontClass *class)
object_class->finalize = pango_cairo_core_text_font_finalize;
/* font_class->describe defined by parent class PangoCoreTextFont. */
font_class->get_glyph_extents = pango_cairo_core_text_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
font_class->describe_absolute = pango_cairo_core_text_font_describe_absolute;
}
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index c8444ed9..0019f83a 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -152,6 +152,7 @@ pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
object_class->finalize = pango_cairo_fc_font_finalize;
font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
fc_font_class->lock_face = pango_cairo_fc_font_lock_face;
fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face;
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index cfe9cb45..a49d14d4 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -185,6 +185,188 @@ _pango_cairo_font_install (PangoFont *font,
return TRUE;
}
+
+static int
+max_glyph_width (PangoLayout *layout)
+{
+ int max_width = 0;
+ GSList *l, *r;
+
+ for (l = pango_layout_get_lines_readonly (layout); l; l = l->next)
+ {
+ PangoLayoutLine *line = l->data;
+
+ for (r = line->runs; r; r = r->next)
+ {
+ PangoGlyphString *glyphs = ((PangoGlyphItem *)r->data)->glyphs;
+ int i;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ if (glyphs->glyphs[i].geometry.width > max_width)
+ max_width = glyphs->glyphs[i].geometry.width;
+ }
+ }
+
+ return max_width;
+}
+
+typedef struct _PangoCairoFontMetricsInfo
+{
+ const char *sample_str;
+ PangoFontMetrics *metrics;
+} PangoCairoFontMetricsInfo;
+
+PangoFontMetrics *
+_pango_cairo_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ PangoCairoFont *cfont = (PangoCairoFont *) font;
+ PangoCairoFontPrivate *cf_priv = PANGO_CAIRO_FONT_PRIVATE (font);
+ PangoCairoFontMetricsInfo *info = NULL; /* Quiet gcc */
+ GSList *tmp_list;
+ static int in_get_metrics;
+
+ const char *sample_str = pango_language_get_sample_string (language);
+
+ tmp_list = cf_priv->metrics_by_lang;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+
+ if (info->sample_str == sample_str) /* We _don't_ need strcmp */
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ cairo_font_options_t *font_options;
+ PangoLayout *layout;
+ PangoRectangle extents;
+ PangoFontDescription *desc;
+ cairo_scaled_font_t *scaled_font;
+ cairo_matrix_t cairo_matrix;
+ PangoMatrix pango_matrix;
+ PangoMatrix identity = PANGO_MATRIX_INIT;
+ glong sample_str_width;
+
+ int height, shift;
+
+ /* XXX this is racy. need a ref'ing getter... */
+ fontmap = pango_font_get_font_map (font);
+ if (!fontmap)
+ return pango_font_metrics_new ();
+ fontmap = g_object_ref (fontmap);
+
+ info = g_slice_new0 (PangoCairoFontMetricsInfo);
+
+ cf_priv->metrics_by_lang = g_slist_prepend (cf_priv->metrics_by_lang, info);
+
+ info->sample_str = sample_str;
+
+ scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv);
+
+ context = pango_font_map_create_context (fontmap);
+ pango_context_set_language (context, language);
+
+ font_options = cairo_font_options_create ();
+ cairo_scaled_font_get_font_options (scaled_font, font_options);
+ pango_cairo_context_set_font_options (context, font_options);
+ cairo_font_options_destroy (font_options);
+
+ info->metrics = (* PANGO_CAIRO_FONT_GET_IFACE (font)->create_base_metrics_for_context) (cfont, context);
+
+ /* We now need to adjust the base metrics for ctm */
+ cairo_scaled_font_get_ctm (scaled_font, &cairo_matrix);
+ pango_matrix.xx = cairo_matrix.xx;
+ pango_matrix.yx = cairo_matrix.yx;
+ pango_matrix.xy = cairo_matrix.xy;
+ pango_matrix.yy = cairo_matrix.yy;
+ pango_matrix.x0 = 0;
+ pango_matrix.y0 = 0;
+ if (G_UNLIKELY (0 != memcmp (&identity, &pango_matrix, 4 * sizeof (double))))
+ {
+ double xscale = pango_matrix_get_font_scale_factor (&pango_matrix);
+ if (xscale) xscale = 1 / xscale;
+
+ info->metrics->ascent *= xscale;
+ info->metrics->descent *= xscale;
+ info->metrics->height *= xscale;
+ info->metrics->underline_position *= xscale;
+ info->metrics->underline_thickness *= xscale;
+ info->metrics->strikethrough_position *= xscale;
+ info->metrics->strikethrough_thickness *= xscale;
+ }
+
+ /* Set the matrix on the context so we don't have to adjust the derived
+ * metrics. */
+ pango_context_set_matrix (context, &pango_matrix);
+
+ /* Ugly. We need to prevent recursion when we call into
+ * PangoLayout to determine approximate char width.
+ */
+ if (!in_get_metrics)
+ {
+ in_get_metrics = 1;
+
+ /* Update approximate_*_width now */
+ layout = pango_layout_new (context);
+ desc = pango_font_describe_with_absolute_size (font);
+ pango_layout_set_font_description (layout, desc);
+ pango_font_description_free (desc);
+
+ pango_layout_set_text (layout, sample_str, -1);
+ pango_layout_get_extents (layout, NULL, &extents);
+
+ sample_str_width = pango_utf8_strwidth (sample_str);
+ g_assert (sample_str_width > 0);
+ info->metrics->approximate_char_width = extents.width / sample_str_width;
+
+ pango_layout_set_text (layout, "0123456789", -1);
+ info->metrics->approximate_digit_width = max_glyph_width (layout);
+
+ g_object_unref (layout);
+ in_get_metrics = 0;
+ }
+
+ /* We may actually reuse ascent/descent we got from cairo here. that's
+ * in cf_priv->font_extents.
+ */
+ height = info->metrics->ascent + info->metrics->descent;
+ switch (cf_priv->gravity)
+ {
+ default:
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ break;
+ case PANGO_GRAVITY_NORTH:
+ info->metrics->ascent = info->metrics->descent;
+ break;
+ case PANGO_GRAVITY_EAST:
+ case PANGO_GRAVITY_WEST:
+ {
+ int ascent = height / 2;
+ if (cf_priv->is_hinted)
+ ascent = PANGO_UNITS_ROUND (ascent);
+ info->metrics->ascent = ascent;
+ }
+ }
+ shift = (height - info->metrics->ascent) - info->metrics->descent;
+ info->metrics->descent += shift;
+ info->metrics->underline_position -= shift;
+ info->metrics->strikethrough_position -= shift;
+ info->metrics->ascent = height - info->metrics->descent;
+
+ g_object_unref (context);
+ g_object_unref (fontmap);
+ }
+
+ return pango_font_metrics_ref (info->metrics);
+}
+
static PangoCairoFontHexBoxInfo *
_pango_cairo_font_private_get_hex_box_info (PangoCairoFontPrivate *cf_priv)
{
@@ -452,6 +634,14 @@ _pango_cairo_font_private_initialize (PangoCairoFontPrivate *cf_priv,
cf_priv->scaled_font = NULL;
cf_priv->hbi = NULL;
cf_priv->glyph_extents_cache = NULL;
+ cf_priv->metrics_by_lang = NULL;
+}
+
+static void
+free_metrics_info (PangoCairoFontMetricsInfo *info)
+{
+ pango_font_metrics_unref (info->metrics);
+ g_slice_free (PangoCairoFontMetricsInfo, info);
}
void
@@ -469,6 +659,10 @@ _pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv)
if (cf_priv->glyph_extents_cache)
g_free (cf_priv->glyph_extents_cache);
cf_priv->glyph_extents_cache = NULL;
+
+ g_slist_foreach (cf_priv->metrics_by_lang, (GFunc)free_metrics_info, NULL);
+ g_slist_free (cf_priv->metrics_by_lang);
+ cf_priv->metrics_by_lang = NULL;
}
gboolean
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index c2c97733..704ae497 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -86,6 +86,8 @@ struct _PangoCairoFontPrivate
PangoRectangle font_extents;
PangoCairoFontGlyphExtentsCacheEntry *glyph_extents_cache;
+
+ GSList *metrics_by_lang;
};
struct _PangoCairoFontIface
diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c
index 6f243262..9f4f5c14 100644
--- a/pango/pangocairo-win32font.c
+++ b/pango/pangocairo-win32font.c
@@ -177,6 +177,7 @@ pango_cairo_win32_font_class_init (PangoCairoWin32FontClass *class)
object_class->finalize = pango_cairo_win32_font_finalize;
font_class->get_glyph_extents = pango_cairo_win32_font_get_glyph_extents;
+ font_class->get_metrics = _pango_cairo_font_get_metrics;
win32_font_class->select_font = pango_cairo_win32_font_select_font;
win32_font_class->done_font = pango_cairo_win32_font_done_font;