[pango/pango1-dwrite: 4/10] PangoWin32: Query font description using DirectWrite




commit c6b0f13b1357d0a655249ac938bc20abb72e298b
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri Jul 15 18:48:43 2022 +0800

    PangoWin32: Query font description using DirectWrite
    
    We now use DirectWrite to query the font weight, stretch, description
    and so on by using first DirectWrite's GdiInterop to convert the
    logfontw into an IDirectWriteFont, since the support in there for
    querying font attributes are more complete in there.  Take out the
    warned fonts items, as DirectWrite would support the font attributes
    that we need much better (i.e. stretch and so on), and the warned fonts
    items will get into the way.
    
    Portions based on Luca Bacci's work for querying the font description
    for Windows using DirectWrite for the upcoming Pango2.

 pango/pangowin32-dwrite-fontmap.cpp | 216 ++++++++++++++++++++++++++++++++++++
 pango/pangowin32-fontmap.c          |  86 +-------------
 pango/pangowin32-private.h          |   8 +-
 3 files changed, 224 insertions(+), 86 deletions(-)
---
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index dd2f506a0..ae1d11af1 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -204,6 +204,222 @@ pango_win32_dwrite_font_is_monospace (gpointer  dwrite_font,
   return result;
 }
 
+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 PangoVariant
+util_to_pango_variant (IDWriteFont *font)
+{
+  PangoVariant variant = PANGO_VARIANT_NORMAL;
+
+  return variant;
+}
+
+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_variant (description, util_to_pango_variant (font));
+  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);
+}
+
+static char*
+util_dwrite_get_font_variant_name (IDWriteFont *font)
+{
+  IDWriteLocalizedStrings *strings = NULL;
+  HRESULT hr;
+
+  hr = font->GetFaceNames (&strings);
+  if (FAILED (hr) || strings == NULL)
+    {
+      g_warning ("IDWriteFont::GetFaceNames failed with error code %x", (unsigned) hr);
+      return NULL;
+    }
+
+  return util_free_to_string (strings);
+}
+
+PangoFontDescription *
+pango_win32_font_description_from_logfontw_dwrite (const 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 = pango_win32_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 ();
+    }
+
+  return desc;
+}
+
 void
 pango_win32_dwrite_font_release (gpointer dwrite_font)
 {
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index 3756c9293..05542f745 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -717,10 +717,6 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
 
   win32fontmap->font_cache = pango_win32_font_cache_new ();
   win32fontmap->freed_fonts = g_queue_new ();
-  win32fontmap->warned_fonts = g_hash_table_new_full (g_str_hash,
-                                                      g_str_equal,
-                                                      g_free,
-                                                      NULL);
 
   pango_win32_dwrite_font_map_populate (win32fontmap);
 
@@ -871,7 +867,6 @@ pango_win32_font_map_finalize (GObject *object)
   pango_win32_font_cache_free (win32fontmap->font_cache);
 
   g_hash_table_destroy (win32fontmap->dwrite_fonts);
-  g_hash_table_destroy (win32fontmap->warned_fonts);
   g_hash_table_destroy (win32fontmap->fonts);
   g_hash_table_destroy (win32fontmap->families);
 
@@ -1568,6 +1563,9 @@ get_family_nameW (const LOGFONTW *lfp)
 PangoFontDescription *
 pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
 {
+  return pango_win32_font_description_from_logfontw_dwrite (lfp);
+
+#if 0 /* XXX: Add GDI fallback? */
   PangoFontDescription *description;
   gchar *family;
   PangoStyle style;
@@ -1604,6 +1602,7 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
   pango_font_description_set_variant (description, variant);
 
   return description;
+#endif
 }
 
 static char *
@@ -1933,14 +1932,9 @@ pango_win32_font_map_load_fontset (PangoFontMap                 *fontmap,
   char **families;
   int i;
   PangoFontsetSimple *fonts;
-  PangoWin32FontMap *win32fontmap = NULL;
-  GHashTable *warned_fonts = NULL;
 
   g_return_val_if_fail (fontmap != NULL, NULL);
 
-  win32fontmap = PANGO_WIN32_FONT_MAP (fontmap);
-  warned_fonts = win32fontmap->warned_fonts;
-
   family = pango_font_description_get_family (desc);
   families = g_strsplit (family ? family : "", ",", -1);
 
@@ -1955,79 +1949,7 @@ pango_win32_font_map_load_fontset (PangoFontMap                 *fontmap,
 
   g_strfreev (families);
 
-  /* The font description was completely unloadable, try with
-   * family == "Sans"
-   */
-  if (pango_fontset_simple_size (fonts) == 0)
-    {
-      char *ctmp1, *ctmp2;
-
-      pango_font_description_set_family_static (tmp_desc,
-                                                pango_font_description_get_family (desc));
-
-      ctmp1 = pango_font_description_to_string (desc);
-      pango_font_description_set_family_static (tmp_desc, "Sans");
-
-      if (!g_hash_table_lookup (warned_fonts, ctmp1))
-        {
-
-          g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
-
-          ctmp2 = pango_font_description_to_string (tmp_desc);
-          g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
-                     "expect ugly output.", ctmp1, ctmp2);
-          g_free (ctmp2);
-        }
-
-      g_free (ctmp1);
-
-      pango_win32_font_map_fontset_add_fonts (fontmap,
-                                              context,
-                                              fonts,
-                                              tmp_desc,
-                                              "Sans");
-    }
-
-  /* We couldn't try with Sans and the specified style. Try Sans Normal */
-  if (pango_fontset_simple_size (fonts) == 0)
-    {
-      char *ctmp1, *ctmp2;
-
-      pango_font_description_set_family_static (tmp_desc, "Sans");
-      ctmp1 = pango_font_description_to_string (tmp_desc);
-      pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
-      pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
-      pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
-      pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
-
-
-      if (!g_hash_table_lookup (warned_fonts, ctmp1))
-        {
-          g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
-
-          ctmp2 = pango_font_description_to_string (tmp_desc);
-
-          g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
-                     "expect ugly output.", ctmp1, ctmp2);
-          g_free (ctmp2);
-        }
-
-      g_free (ctmp1);
-
-      pango_win32_font_map_fontset_add_fonts (fontmap,
-                                              context,
-                                              fonts,
-                                              tmp_desc,
-                                              "Sans");
-    }
-
   pango_font_description_free (tmp_desc);
 
-  /* Everything failed, we are screwed, there is no way to continue,
-   * but lets just not crash here.
-   */
-  if (pango_fontset_simple_size (fonts) == 0)
-    g_warning ("All font fallbacks failed!!!!");
-
   return PANGO_FONTSET (fonts);
 }
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index 1d843ec2d..d0ef6dbc7 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -107,9 +107,6 @@ struct _PangoWin32FontMap
   /* keeps track of the system font aliases that we might have */
   GHashTable *aliases;
 
-  /* keeps track of the warned fonts that we might have */
-  GHashTable *warned_fonts;
-
   double resolution;           /* (points / pixel) * PANGO_SCALE */
 };
 
@@ -307,7 +304,10 @@ gboolean               pango_win32_dwrite_font_is_monospace   (gpointer
 
 void                   pango_win32_dwrite_font_release        (gpointer               dwrite_font);
 
-gpointer               pango_win32_logfontw_get_dwrite_font   (LOGFONTW *logfontw);
+gpointer               pango_win32_logfontw_get_dwrite_font   (LOGFONTW              *logfontw);
+
+PangoFontDescription *
+pango_win32_font_description_from_logfontw_dwrite             (const LOGFONTW        *logfontw);
 
 G_END_DECLS
 


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