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




commit babd9425860cdcebc842534f5879d5f801d7b403
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.

 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]