[pango/pango1-dwrite: 2/2] PangoWin32: Implement is_hinted on Windows using DirectWrite




commit f01a692f9525ad72ba9ccd6529de133f311c4a31
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Thu Jul 21 14:53:42 2022 +0800

    PangoWin32: Implement is_hinted on Windows using DirectWrite
    
    ... by querying the font table 'gasp' and see whether the bits needed
    for hinting are there.  Codewise, it is simpler with GDI+, but it would
    then require more overhead since GDI(+) operations are needed (this means
    "slower") and we need to put boilerplates for using GDI+ from our
    plain-C code.

 pango/pangocairo-win32font.c        |  1 +
 pango/pangowin32-dwrite-fontmap.cpp | 83 +++++++++++++++++++++++++++++++++++++
 pango/pangowin32-fontmap.c          |  1 +
 pango/pangowin32-private.h          |  6 +++
 pango/pangowin32.c                  | 13 ++++++
 5 files changed, 104 insertions(+)
---
diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c
index 9f4f5c140..5b860bab8 100644
--- a/pango/pangocairo-win32font.c
+++ b/pango/pangocairo-win32font.c
@@ -268,6 +268,7 @@ _pango_cairo_win32_font_new (PangoCairoWin32FontMap     *cwfontmap,
                                       win32font->size,
                                       &win32font->logfontw);
 
+  win32font->is_hinted = pango_win32_dwrite_font_check_is_hinted (win32font);
   cairo_matrix_init_identity (&font_matrix);
 
   cairo_matrix_scale (&font_matrix, size, size);
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index 2d83eafe4..916891c7f 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -422,6 +422,89 @@ pango_win32_font_description_from_logfontw_dwrite (const LOGFONTW *logfontw)
   return desc;
 }
 
+/* macros to help parse the 'gasp' font table, referring to FreeType2 */
+#define DWRITE_UCHAR_USHORT( p, i, s ) ( (unsigned short)( ((const unsigned char *)(p))[(i)] ) << (s) )
+
+#define DWRITE_PEEK_USHORT( p ) (unsigned short)( DWRITE_UCHAR_USHORT( p, 0, 8 ) | DWRITE_UCHAR_USHORT( p, 
1, 0 ) )
+
+#define DWRITE_NEXT_USHORT( buffer ) ( (unsigned short)( buffer += 2, DWRITE_PEEK_USHORT( buffer - 2 ) ) )
+
+/* values to indicate that grid fit (hinting) is supported by the font */
+#define GASP_GRIDFIT 0x0001
+#define GASP_SYMMETRIC_GRIDFIT 0x0004
+
+gboolean
+pango_win32_dwrite_font_check_is_hinted (PangoWin32Font *font)
+{
+  IDWriteFont *dwrite_font = NULL;
+  IDWriteFontFace *dwrite_font_face = NULL;
+  gboolean failed = FALSE;
+  gboolean result = FALSE;
+  gboolean dwrite_font_release = FALSE;
+
+  gboolean succeeded = FALSE;
+  PangoWin32DWriteItems *dwrite_items = pango_win32_get_direct_write_items ();
+  dwrite_font = (IDWriteFont *) g_hash_table_lookup (PANGO_WIN32_FONT_MAP (font->fontmap)->dwrite_fonts,
+                                                    &font->logfontw);
+
+  /* create the IDWriteFont from the logfont underlying the PangoWin32Font if needed */
+  if (dwrite_font == NULL)
+    {
+      if (FAILED (dwrite_items->gdi_interop->CreateFontFromLOGFONT (&font->logfontw,
+                                                                    &dwrite_font)) ||
+                  dwrite_font == NULL)
+        failed = TRUE;
+      else
+        dwrite_font_release = TRUE;
+    }
+
+  if (!failed && SUCCEEDED (dwrite_font->CreateFontFace (&dwrite_font_face)) && dwrite_font_face != NULL)
+    {
+      UINT32 gasp_tag = DWRITE_MAKE_OPENTYPE_TAG ('g', 'a', 's', 'p');
+      UINT32 table_size;
+      const unsigned short *table_data;
+      void *table_ctx;
+      gboolean exists;
+
+      /* The 'gasp' table may not exist for the font, so no 'gasp' == no hinting */
+      if (SUCCEEDED (dwrite_font_face->TryGetFontTable (gasp_tag,
+                                                        (const void **)(&table_data),
+                                                       &table_size,
+                                                       &table_ctx,
+                                                       &exists)))
+        {
+          if (exists)
+            {
+              guint16 version = DWRITE_NEXT_USHORT (table_data);
+
+              if (version == 0 || version == 1)
+                {
+                  guint16 num_ranges = DWRITE_NEXT_USHORT (table_data);
+                  guint16 i;
+
+                  for (i = 0; !result && i < num_ranges && i < (table_size / sizeof (guint16)); i ++)
+                    {
+                      guint16 ppem = DWRITE_NEXT_USHORT (table_data);
+                      guint16 behavior = DWRITE_NEXT_USHORT (table_data);
+
+                      if (behavior & (GASP_GRIDFIT | GASP_SYMMETRIC_GRIDFIT))
+                        result = TRUE;
+                    }
+                }
+            }
+
+          dwrite_font_face->ReleaseFontTable (table_ctx);
+        }
+
+      dwrite_font_face->Release ();
+    }
+
+  if (dwrite_font_release)
+    dwrite_font->Release ();
+
+  return result;
+}
+
 void
 pango_win32_dwrite_font_release (gpointer dwrite_font)
 {
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index 627b24efc..836a3e465 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -1152,6 +1152,7 @@ pango_win32_font_neww (PangoFontMap   *fontmap,
 
   result->size = size;
   _pango_win32_make_matching_logfontw (fontmap, lfp, size, &result->logfontw);
+  result->is_hinted = pango_win32_dwrite_font_check_is_hinted (result);
 
   return result;
 }
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index b8ade516f..db2eb5042 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -145,6 +145,9 @@ struct _PangoWin32Font
    */
   gboolean in_cache;
   GHashTable *glyph_info;
+
+  /* whether the font supports hinting */
+  gboolean is_hinted;
 };
 
 struct _PangoWin32FontClass
@@ -287,6 +290,9 @@ _PANGO_EXTERN
 gpointer        _pango_win32_copy_cmap (gpointer cmap,
                                         guint16 cmap_format);
 
+_PANGO_EXTERN
+gboolean        pango_win32_dwrite_font_check_is_hinted       (PangoWin32Font    *font);
+
 extern gboolean _pango_win32_debug;
 
 void                   pango_win32_insert_font                (PangoWin32FontMap     *win32fontmap,
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 55a079c9f..5a26ee98b 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -56,6 +56,7 @@ static gboolean pango_win32_font_real_select_font      (PangoFont *font,
                                                        HDC        hdc);
 static void     pango_win32_font_real_done_font        (PangoFont *font);
 static double   pango_win32_font_real_get_metrics_factor (PangoFont *font);
+static gboolean pango_win32_font_is_hinted             (PangoFont *font);
 
 static void                  pango_win32_get_item_properties    (PangoItem        *item,
                                                                 PangoUnderline   *uline,
@@ -202,6 +203,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+  PangoFontClassPrivate *pclass;
 
   object_class->finalize = pango_win32_font_finalize;
   object_class->dispose = pango_win32_font_dispose;
@@ -218,6 +220,9 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
   class->done_font = pango_win32_font_real_done_font;
   class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
 
+  pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT);
+  pclass->is_hinted = pango_win32_font_is_hinted;
+
   _pango_win32_get_display_dc ();
 }
 
@@ -662,6 +667,14 @@ pango_win32_font_real_get_metrics_factor (PangoFont *font)
   return PANGO_SCALE;
 }
 
+static gboolean
+pango_win32_font_is_hinted (PangoFont *font)
+{
+  g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), FALSE);
+
+  return PANGO_WIN32_FONT (font)->is_hinted;
+}
+
 /**
  * pango_win32_font_logfont:
  * @font: a `PangoFont` which must be from the Win32 backend


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