[pango/pango1-dwrite] pangowin32: Use DirectWrite to query font properties




commit 151a9c747b39212038af5ec1e91fd0820d95995f
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri Jul 8 18:12:53 2022 +0800

    pangowin32: Use DirectWrite to query font properties
    
    ...if available, when using LOGFONTWs only for now.  Also move DirectWrite
    initlialization into a function of its own since we will well need to set
    it up when querying the font properties using DirectWrite.
    
    DirectWrite font querying to PangoDescription mapping code based on Luca
    Bacci's DirectWrite fontmap code in the upcoming Pango2.

 pango/pangowin32-dwrite-fontmap.cpp | 229 +++++++++++++++++++++++++++++++++---
 pango/pangowin32-fontmap.c          |   4 +
 pango/pangowin32-private.h          |  17 +--
 3 files changed, 228 insertions(+), 22 deletions(-)
---
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index e7c7bc9c1..84d44d44a 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -46,8 +46,8 @@ struct _PangoWin32DWriteItems
   IDWriteGdiInterop *gdi_interop;
 };
 
-void
-pango_win32_dwrite_font_map_init (PangoWin32FontMap *map)
+PangoWin32DWriteItems *
+init_direct_write (void)
 {
   PangoWin32DWriteItems *dwrite_items = g_new0 (PangoWin32DWriteItems, 1);
   HRESULT hr;
@@ -57,27 +57,32 @@ pango_win32_dwrite_font_map_init (PangoWin32FontMap *map)
                             UUID_OF_IDWriteFactory,
                             reinterpret_cast<IUnknown**> (&dwrite_items->dwrite_factory));
 
-  if (FAILED (hr) || dwrite_items->dwrite_factory == NULL)
+  if (SUCCEEDED (hr) && dwrite_items->dwrite_factory != NULL)
     {
-      g_error ("DWriteCreateFactory failed with error code %x", (unsigned)hr);
-      failed = TRUE;
+      hr = dwrite_items->dwrite_factory->GetGdiInterop (&dwrite_items->gdi_interop);
+      if (FAILED (hr) || dwrite_items->gdi_interop == NULL)
+        {
+          g_error ("DWriteCreateFactory::GetGdiInterop failed with error code %x", (unsigned)hr);
+          dwrite_items->dwrite_factory->Release ();
+          failed = TRUE;
+        }
     }
-
-  hr = dwrite_items->dwrite_factory->GetGdiInterop (&dwrite_items->gdi_interop);
-
-  if (FAILED (hr) || dwrite_items->gdi_interop == NULL)
+  else
     {
-      g_error ("DWriteCreateFactory::GetGdiInterop failed with error code %x", (unsigned)hr);
+      g_error ("DWriteCreateFactory failed with error code %x", (unsigned)hr);
       failed = TRUE;
     }
 
   if (failed)
-    {
-      if (dwrite_items->dwrite_factory != NULL)
-        dwrite_items->dwrite_factory->Release ();
+    g_free (dwrite_items);
 
-      return;
-    }
+  return failed ? NULL : dwrite_items;
+}
+
+void
+pango_win32_dwrite_font_map_init (PangoWin32FontMap *map)
+{
+  PangoWin32DWriteItems *dwrite_items = init_direct_write ();
 
   map->dwrite_items = dwrite_items;
 }
@@ -190,6 +195,200 @@ pango_win32_font_map_logfontw_get_dwrite_font (PangoWin32FontMap *map,
   return font;
 }
 
+static PangoStretch
+util_to_pango_stretch (DWRITE_FONT_STRETCH stretch)
+{
+  PangoStretch pango_stretch = PANGO_STRETCH_NORMAL;
+
+  switch (stretch)
+    {
+      case DWRITE_FONT_STRETCH_ULTRA_CONDENSED:
+        pango_stretch = PANGO_STRETCH_ULTRA_CONDENSED;
+        break;
+      case DWRITE_FONT_STRETCH_EXTRA_CONDENSED:
+        pango_stretch = PANGO_STRETCH_EXTRA_CONDENSED;
+        break;
+      case DWRITE_FONT_STRETCH_CONDENSED:
+        pango_stretch = PANGO_STRETCH_CONDENSED;
+        break;
+      case DWRITE_FONT_STRETCH_SEMI_CONDENSED:
+        pango_stretch = PANGO_STRETCH_SEMI_CONDENSED;
+        break;
+      case DWRITE_FONT_STRETCH_NORMAL:
+        /* also DWRITE_FONT_STRETCH_MEDIUM */
+        pango_stretch = PANGO_STRETCH_NORMAL;
+        break;
+      case DWRITE_FONT_STRETCH_SEMI_EXPANDED:
+        pango_stretch = PANGO_STRETCH_SEMI_EXPANDED;
+        break;
+      case DWRITE_FONT_STRETCH_EXPANDED:
+        pango_stretch = PANGO_STRETCH_EXPANDED;
+        break;
+      case DWRITE_FONT_STRETCH_EXTRA_EXPANDED:
+        pango_stretch = PANGO_STRETCH_EXTRA_EXPANDED;
+        break;
+      case DWRITE_FONT_STRETCH_ULTRA_EXPANDED:
+        pango_stretch = PANGO_STRETCH_ULTRA_EXPANDED;
+        break;
+      case DWRITE_FONT_STRETCH_UNDEFINED:
+      default:
+        pango_stretch = PANGO_STRETCH_NORMAL;
+    }
+
+  return pango_stretch;
+}
+
+static PangoStyle
+util_to_pango_style (DWRITE_FONT_STYLE style)
+{
+  switch (style)
+    {
+    case DWRITE_FONT_STYLE_NORMAL:
+      return PANGO_STYLE_NORMAL;
+    case DWRITE_FONT_STYLE_OBLIQUE:
+      return PANGO_STYLE_OBLIQUE;
+    case DWRITE_FONT_STYLE_ITALIC:
+      return PANGO_STYLE_ITALIC;
+    default:
+      g_assert_not_reached ();
+      return PANGO_STYLE_NORMAL;
+    }
+}
+
+static int
+util_map_weight (int weight)
+{
+  if G_UNLIKELY (weight < 100)
+    weight = 100;
+
+  if G_UNLIKELY (weight > 1000)
+    weight = 1000;
+
+  return weight;
+}
+
+static PangoWeight
+util_to_pango_weight (DWRITE_FONT_WEIGHT weight)
+{
+  /* DirectWrite weight values range from 1 to 999, Pango weight values
+   * range from 100 to 1000. */
+
+  return (PangoWeight) util_map_weight (weight);
+}
+
+static PangoFontDescription*
+util_get_pango_font_description (IDWriteFont *font,
+                                  const char *family_name)
+{
+  DWRITE_FONT_STRETCH stretch = font->GetStretch ();
+  DWRITE_FONT_STYLE style = font->GetStyle ();
+  DWRITE_FONT_WEIGHT weight = font->GetWeight ();
+  PangoFontDescription *description;
+
+  description = pango_font_description_new ();
+  pango_font_description_set_family (description, family_name);
+  pango_font_description_set_stretch (description, util_to_pango_stretch (stretch));
+  pango_font_description_set_style (description, util_to_pango_style (style));
+  pango_font_description_set_weight (description, util_to_pango_weight (weight));
+
+  return description;
+}
+
+static char*
+util_free_to_string (IDWriteLocalizedStrings *strings)
+{
+  char *string = NULL;
+  HRESULT hr;
+
+  if (strings->GetCount() > 0)
+    {
+      UINT32 index = 0;
+      BOOL exists = FALSE;
+      UINT32 length = 0;
+
+      hr = strings->FindLocaleName (L"en-us", &index, &exists);
+      if (FAILED (hr) || !exists || index == UINT32_MAX)
+        index = 0;
+
+      hr = strings->GetStringLength (index, &length);
+      if (SUCCEEDED (hr) && length > 0)
+        {
+          gunichar2 *string_utf16 = g_new (gunichar2, length + 1);
+
+          hr = strings->GetString (index, (wchar_t*) string_utf16, length + 1);
+          if (SUCCEEDED (hr))
+            string = g_utf16_to_utf8 (string_utf16, -1, NULL, NULL, NULL);
+
+          g_free (string_utf16);
+        }
+    }
+
+  strings->Release ();
+
+  return string;
+}
+
+static char*
+util_dwrite_get_font_family_name (IDWriteFontFamily *family)
+{
+  IDWriteLocalizedStrings *strings = NULL;
+  HRESULT hr;
+
+  hr = family->GetFamilyNames (&strings);
+  if (FAILED (hr) || strings == NULL)
+    {
+      g_warning ("IDWriteFontFamily::GetFamilyNames failed with error code %x", (unsigned) hr);
+      return NULL;
+    }
+
+  return util_free_to_string (strings);
+}
+
+PangoFontDescription *
+pango_win32_font_description_from_logfontw_dwrite (LOGFONTW *logfontw)
+{
+  PangoFontDescription *desc = NULL;
+  IDWriteFont *font = NULL;
+  HRESULT hr;
+  gchar *family;
+  PangoStyle style;
+  PangoVariant variant;
+  PangoWeight weight;
+  PangoStretch stretch;
+  PangoWin32DWriteItems *dwrite_items;
+
+  dwrite_items = init_direct_write ();
+  if (dwrite_items == NULL)
+    return NULL;
+
+  hr = dwrite_items->gdi_interop->CreateFontFromLOGFONT (logfontw, &font);
+
+  if (SUCCEEDED (hr) && font != NULL)
+    {
+      IDWriteFontFamily *family = NULL;
+
+      hr = font->GetFontFamily (&family);
+
+      if (SUCCEEDED (hr) && family != NULL)
+        {
+          char *family_name = util_dwrite_get_font_family_name (family);
+
+          if (family_name != NULL)
+            desc = util_get_pango_font_description (font, family_name);
+
+          family->Release ();
+        }
+
+      font->Release ();
+    }
+
+  dwrite_items->gdi_interop->Release ();
+  dwrite_items->dwrite_factory->Release ();
+  g_free (dwrite_items);
+
+  return desc;
+}
+
 void
 pango_win32_dwrite_font_release (gpointer dwrite_font)
 {
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index e91f1bbe3..62b026305 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -1567,6 +1567,7 @@ get_family_nameW (const LOGFONTW *lfp)
 PangoFontDescription *
 pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
 {
+#ifndef HAVE_DIRECTWRITE
   PangoFontDescription *description;
   gchar *family;
   PangoStyle style;
@@ -1603,6 +1604,9 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
   pango_font_description_set_variant (description, variant);
 
   return description;
+#else /* !HAVE_DIRECTWRITE */
+  return pango_win32_font_description_from_logfontw_dwrite (lfp);
+#endif
 }
 
 static char *
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index ea574c0e5..99f8a596c 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -293,20 +293,23 @@ gpointer        _pango_win32_copy_cmap (gpointer cmap,
 extern gboolean _pango_win32_debug;
 
 
-void            pango_win32_insert_font              (PangoWin32FontMap *win32fontmap,
-                                                      LOGFONTW          *lfp,
-                                                      gpointer           dwrite_font,
-                                                      gboolean           is_synthetic);
+void            pango_win32_insert_font                       (PangoWin32FontMap *win32fontmap,
+                                                               LOGFONTW          *lfp,
+                                                               gpointer           dwrite_font,
+                                                               gboolean           is_synthetic);
 
-void            pango_win32_dwrite_font_map_init     (PangoWin32FontMap *map);
+void            pango_win32_dwrite_font_map_init              (PangoWin32FontMap *map);
 
-void            pango_win32_dwrite_font_map_populate (PangoWin32FontMap *map);
+void            pango_win32_dwrite_font_map_populate          (PangoWin32FontMap *map);
 
-void            pango_win32_dwrite_font_map_destroy  (PangoWin32FontMap *map);
+void            pango_win32_dwrite_font_map_destroy           (PangoWin32FontMap *map);
 
 gpointer        pango_win32_font_map_logfontw_get_dwrite_font (PangoWin32FontMap *map,
                                                                LOGFONTW *logfontw);
 
+PangoFontDescription *
+pango_win32_font_description_from_logfontw_dwrite             (LOGFONTW *logfontw);
+
 void            pango_win32_dwrite_font_release      (gpointer dwrite_font);
 
 G_END_DECLS


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