summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2022-07-15 18:48:43 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2022-09-26 11:04:25 +0800
commit894821e8b4593ece2437481fd607022b36d94f1f (patch)
treed52f84d460a989e4b4aab50d17a25530efb1f444
parent43f3d8b3c22a02b83a3221bd7a0de52a88524c07 (diff)
downloadpango-894821e8b4593ece2437481fd607022b36d94f1f.tar.gz
PangoWin32: Query font descriptions using DirectWrite on LOGFONTW's
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.
-rw-r--r--pango/pangowin32-dwrite-fontmap.cpp216
-rw-r--r--pango/pangowin32-fontmap.c86
-rw-r--r--pango/pangowin32-private.h8
3 files changed, 224 insertions, 86 deletions
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index dd2f506a..ae1d11af 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 3756c929..05542f74 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 1d843ec2..d0ef6dbc 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