[pango] Revert "Drop cairo metrics implementation"



commit 1fe467589cbd6b407eabe6fbb8a8b2cd4beedc1b
Author: Khaled Hosny <khaledhosny eglug org>
Date:   Wed Aug 14 18:15:34 2019 +0200

    Revert "Drop cairo metrics implementation"
    
    This reverts commit c5d86c368128bb9a0be913829da79649fb81f486.
    
    Closes #409

 pango/pangocairo-coretextfont.c |   1 +
 pango/pangocairo-fcfont.c       |   1 +
 pango/pangocairo-font.c         | 194 ++++++++++++++++++++++++++++++++++++++++
 pango/pangocairo-private.h      |   2 +
 pango/pangocairo-win32font.c    |   1 +
 5 files changed, 199 insertions(+)
---
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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]