[pango/bring-back-better-rounding] shape: Bring back careful rounding code




commit eff52d10572b9656ba4c7e68ef85f588df4ed81b
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Jun 27 11:31:13 2021 -0400

    shape: Bring back careful rounding code
    
    When we added the round-glyph-positions option in
    c43da2d3 and b5634799, we lost some code that was careful
    to round in device coordinates.
    
    The reason we lost it is that the rounding needs fontconfig-
    specific data that is only available in the backend, and the
    rounding now happens in the frontend.
    
    Bringing it back is annoying, since we've run out of vfunc
    slots to get info from the backend. This commit works around
    that limitation in a hacky way.
    
    Fixes: #562

 pango/shape.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 4 deletions(-)
---
diff --git a/pango/shape.c b/pango/shape.c
index 04407732..090eb22e 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -151,6 +151,32 @@ fallback_shape (const char          *text,
     pango_glyph_string_reverse_range (glyphs, 0, glyphs->num_glyphs);
 }
 
+/* FIXME: This is very ugly. We are of room for vfuncs, so we can't
+ * easily add api to get is_hinted and the matrix from the PangoFcFont.
+ *
+ * Keep in sync with pangofc-font.h!
+ */
+struct _PangoFcFont
+{
+  PangoFont parent_instance;
+
+  gpointer font_pattern;          /* fully resolved pattern */
+  PangoFontMap *fontmap;            /* associated map */
+  gpointer priv;                    /* used internally */
+  PangoMatrix matrix;               /* used internally */
+  PangoFontDescription *description;
+
+  GSList *metrics_by_lang;
+
+  guint is_hinted : 1;
+  guint is_transformed : 1;
+};
+typedef struct _PangoFcFont PangoFcFont;
+
+#define PANGO_IS_FC_FONT(obj) \
+  g_type_is_a (((GTypeInstance*)obj)->g_class->g_type, \
+  g_type_from_name ("PangoFcFont"))
+
 /**
  * pango_shape_with_flags:
  * @item_text: valid UTF-8 text to shape
@@ -294,11 +320,54 @@ pango_shape_with_flags (const gchar         *item_text,
 
   if (flags & PANGO_SHAPE_ROUND_POSITIONS)
     {
-      for (i = 0; i < glyphs->num_glyphs; i++)
+      if (PANGO_IS_FC_FONT (analysis->font))
         {
-          glyphs->glyphs[i].geometry.width    = PANGO_UNITS_ROUND (glyphs->glyphs[i].geometry.width );
-          glyphs->glyphs[i].geometry.x_offset = PANGO_UNITS_ROUND (glyphs->glyphs[i].geometry.x_offset);
-          glyphs->glyphs[i].geometry.y_offset = PANGO_UNITS_ROUND (glyphs->glyphs[i].geometry.y_offset);
+          PangoFcFont *fc_font = (PangoFcFont *)analysis->font;
+          if (fc_font->is_hinted)
+            {
+              double x_scale_inv, y_scale_inv;
+              double x_scale, y_scale;
+
+              x_scale_inv = y_scale_inv = 1.0;
+              pango_matrix_get_font_scale_factors (&fc_font->matrix, &x_scale_inv, &y_scale_inv);
+              if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
+                {
+                  x_scale_inv = -x_scale_inv;
+                  y_scale_inv = -y_scale_inv;
+                }
+              x_scale = 1. / x_scale_inv;
+              y_scale = 1. / y_scale_inv;
+
+              if (x_scale == 1.0 && y_scale == 1.0)
+                {
+                  for (i = 0; i < glyphs->num_glyphs; i++)
+                    glyphs->glyphs[i].geometry.width = PANGO_UNITS_ROUND (glyphs->glyphs[i].geometry.width);
+                }
+              else
+                {
+    #if 0
+                  if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
+                    {
+                      /* XXX */
+                      double tmp = x_scale;
+                      x_scale = y_scale;
+                      y_scale = -tmp;
+                    }
+    #endif
+    #define HINT(value, scale_inv, scale) (PANGO_UNITS_ROUND ((int) ((value) * scale)) * scale_inv)
+    #define HINT_X(value) HINT ((value), x_scale, x_scale_inv)
+    #define HINT_Y(value) HINT ((value), y_scale, y_scale_inv)
+                  for (i = 0; i < glyphs->num_glyphs; i++)
+                    {
+                      glyphs->glyphs[i].geometry.width    = HINT_X (glyphs->glyphs[i].geometry.width);
+                      glyphs->glyphs[i].geometry.x_offset = HINT_X (glyphs->glyphs[i].geometry.x_offset);
+                      glyphs->glyphs[i].geometry.y_offset = HINT_Y (glyphs->glyphs[i].geometry.y_offset);
+                    }
+    #undef HINT_Y
+    #undef HINT_X
+    #undef HINT
+                }
+            }
         }
     }
 }


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