[pango/pango1-dwrite: 13/24] pangowin32: Use DirectWrite to enumerate system fonts
- From: Chun-wei Fan <fanchunwei src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/pango1-dwrite: 13/24] pangowin32: Use DirectWrite to enumerate system fonts
- Date: Mon, 26 Sep 2022 03:04:49 +0000 (UTC)
commit 5bc16f7896ba3eb5b37ffdb03f28c646aad5889e
Author: Chun-wei Fan <fanchunwei src gnome org>
Date: Thu Jul 7 12:36:26 2022 +0800
pangowin32: Use DirectWrite to enumerate system fonts
...instead of using EnumFontFamiliesEx(), and retrieve the LOGFONTW's that we
need via DirectWrite's GDI interop. Also cache up our IDWriteFont's that we
obtained, so that we can use DirectWrite to query font properties better
than what GDI/Uniscribe can do for us, such as obtaining stretch info from
the font. Also update synthesize_foreach() accordingly, since we should
also record the IDWriteFonts as well for synthesized LOGFONTWs.
Portions based on Luca Bacci's implementation of the DirectWrite fontmap
support in the upcoming Pango2.
pango/pangowin32-dwrite-fontmap.cpp | 105 ++++++++++++++++++++++++++++++++++++
pango/pangowin32-fontmap.c | 35 +++++++-----
pango/pangowin32-private.h | 16 ++++++
3 files changed, 144 insertions(+), 12 deletions(-)
---
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index bb22efea2..0a0278a98 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -84,3 +84,108 @@ pango_win32_dwrite_items_destroy (PangoWin32DWriteItems *dwrite_items)
g_free (dwrite_items);
}
+
+void
+pango_win32_dwrite_font_map_populate (PangoWin32FontMap *map)
+{
+ IDWriteFontCollection *collection = NULL;
+ UINT32 count;
+ HRESULT hr;
+ gboolean failed = FALSE;
+ PangoWin32DWriteItems *dwrite_items = pango_win32_get_direct_write_items ();
+
+ hr = dwrite_items->dwrite_factory->GetSystemFontCollection (&collection, FALSE);
+ if (FAILED (hr) || collection == NULL)
+ {
+ g_error ("IDWriteFactory::GetSystemFontCollection failed with error code %x\n", (unsigned)hr);
+ return;
+ }
+
+ count = collection->GetFontFamilyCount ();
+
+ for (UINT32 i = 0; i < count; i++)
+ {
+ IDWriteFontFamily *family = NULL;
+ UINT32 font_count;
+
+ hr = collection->GetFontFamily (i, &family);
+ if G_UNLIKELY (FAILED (hr) || family == NULL)
+ {
+ g_warning ("IDWriteFontCollection::GetFontFamily failed with error code %x\n", (unsigned)hr);
+ continue;
+ }
+
+ font_count = family->GetFontCount ();
+
+ for (UINT32 j = 0; j < font_count; j++)
+ {
+ IDWriteFont *font = NULL;
+ IDWriteFontFace *face = NULL;
+ DWRITE_FONT_FACE_TYPE font_face_type;
+
+ hr = family->GetFont (j, &font);
+ if (FAILED (hr) || font == NULL)
+ {
+ g_warning ("IDWriteFontFamily::GetFont failed with error code %x\n", (unsigned)hr);
+ break;
+ }
+
+ hr = font->CreateFontFace (&face);
+ if (FAILED (hr) || face == NULL)
+ {
+ g_warning ("IDWriteFont::CreateFontFace failed with error code %x\n", (unsigned)hr);
+ font->Release ();
+ continue;
+ }
+
+ font_face_type = face->GetType ();
+
+ /* don't include Type-1 fonts */
+ if (font_face_type != DWRITE_FONT_FACE_TYPE_TYPE1)
+ {
+ LOGFONTW lfw;
+ BOOL is_sys_font;
+
+ hr = dwrite_items->gdi_interop->ConvertFontToLOGFONT (font, &lfw, &is_sys_font);
+
+ if (SUCCEEDED (hr))
+ pango_win32_insert_font (map, &lfw, font, FALSE);
+ else
+ g_warning ("GDIInterop::ConvertFontToLOGFONT failed with error code %x\n",
+ (unsigned)hr);
+ }
+
+ face->Release ();
+ }
+
+ family->Release ();
+ }
+
+ collection->Release ();
+ collection = NULL;
+}
+
+gpointer
+pango_win32_logfontw_get_dwrite_font (LOGFONTW *logfontw)
+{
+ PangoWin32DWriteItems *dwrite_items = pango_win32_get_direct_write_items ();
+ IDWriteFont *font = NULL;
+ HRESULT hr;
+
+ hr = dwrite_items->gdi_interop->CreateFontFromLOGFONT (logfontw, &font);
+
+ if (FAILED (hr) || font == NULL)
+ g_warning ("IDWriteFactory::GdiInterop::CreateFontFromLOGFONT failed with error %x\n",
+ (unsigned)hr);
+
+ return font;
+}
+
+void
+pango_win32_dwrite_font_release (gpointer dwrite_font)
+{
+ IDWriteFont *font = static_cast<IDWriteFont *>(dwrite_font);
+
+ if (font != NULL)
+ font->Release ();
+}
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index be6daa788..9a1407026 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -101,10 +101,6 @@ static PangoFont *pango_win32_font_map_real_find_font (PangoWin32FontMap
static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);
-static void pango_win32_insert_font (PangoWin32FontMap *fontmap,
- LOGFONTW *lfp,
- gboolean is_synthetic);
-
static PangoWin32Family *pango_win32_get_font_family (PangoWin32FontMap *win32fontmap,
const char *family_name);
@@ -197,7 +193,7 @@ pango_win32_inner_enum_proc (LOGFONTW *lfp,
* Asian fonts with @ prepended to their name, ignore them.
*/
if (lfp->lfFaceName[0] != '@')
- pango_win32_insert_font (win32fontmap, lfp, FALSE);
+ pango_win32_insert_font (win32fontmap, lfp, NULL, FALSE);
return 1;
}
@@ -282,7 +278,7 @@ synthesize_foreach (gpointer key,
lf = variant[NORMAL]->logfontw;
lf.lfWeight = FW_BOLD;
- pango_win32_insert_font (win32fontmap, &lf, TRUE);
+ pango_win32_insert_font (win32fontmap, &lf, NULL, TRUE);
}
if (variant[NORMAL] != NULL && variant[SLANTED] == NULL)
@@ -290,7 +286,7 @@ synthesize_foreach (gpointer key,
lf = variant[NORMAL]->logfontw;
lf.lfItalic = 255;
- pango_win32_insert_font (win32fontmap, &lf, TRUE);
+ pango_win32_insert_font (win32fontmap, &lf, NULL, TRUE);
}
if (variant[NORMAL] != NULL &&
@@ -300,7 +296,7 @@ synthesize_foreach (gpointer key,
lf.lfWeight = FW_BOLD;
lf.lfItalic = 255;
- pango_win32_insert_font (win32fontmap, &lf, TRUE);
+ pango_win32_insert_font (win32fontmap, &lf, NULL, TRUE);
}
else if (variant[BOLDER] != NULL &&
variant[BOLDER+SLANTED] == NULL)
@@ -308,7 +304,7 @@ synthesize_foreach (gpointer key,
lf = variant[BOLDER]->logfontw;
lf.lfItalic = 255;
- pango_win32_insert_font (win32fontmap, &lf, TRUE);
+ pango_win32_insert_font (win32fontmap, &lf, NULL, TRUE);
}
else if (variant[SLANTED] != NULL &&
variant[BOLDER+SLANTED] == NULL)
@@ -316,7 +312,7 @@ synthesize_foreach (gpointer key,
lf = variant[SLANTED]->logfontw;
lf.lfWeight = FW_BOLD;
- pango_win32_insert_font (win32fontmap, &lf, TRUE);
+ pango_win32_insert_font (win32fontmap, &lf, NULL, TRUE);
}
}
@@ -705,7 +701,7 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
{
LOGFONTW logfont;
HDC hdc = _pango_win32_get_display_dc ();
- struct EnumProcData enum_proc_data;
+ struct EnumProcData enum_proc_data = {hdc, win32fontmap};
win32fontmap->families =
g_hash_table_new_full ((GHashFunc) case_insensitive_str_hash,
@@ -713,6 +709,11 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
win32fontmap->fonts =
g_hash_table_new_full ((GHashFunc) logfontw_nosize_hash,
(GEqualFunc) logfontw_nosize_equal, NULL, g_free);
+ win32fontmap->dwrite_fonts =
+ g_hash_table_new_full ((GHashFunc) logfontw_nosize_hash,
+ (GEqualFunc) logfontw_nosize_equal,
+ NULL,
+ pango_win32_dwrite_font_release);
win32fontmap->font_cache = pango_win32_font_cache_new ();
win32fontmap->freed_fonts = g_queue_new ();
@@ -721,6 +722,9 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
g_free,
NULL);
+ pango_win32_dwrite_font_map_populate (win32fontmap);
+
+#if 0 /* XXX: Implement fallback mode to GDI? */
memset (&logfont, 0, sizeof (logfont));
logfont.lfCharSet = DEFAULT_CHARSET;
@@ -730,6 +734,7 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap)
EnumFontFamiliesExW (hdc, &logfont,
(FONTENUMPROCW) pango_win32_enum_proc,
(LPARAM) &enum_proc_data, 0);
+#endif
g_hash_table_foreach (win32fontmap->families, synthesize_foreach, win32fontmap);
@@ -865,6 +870,7 @@ 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);
@@ -1651,9 +1657,10 @@ ff_name (int ff, char* num)
}
}
-static void
+void
pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
LOGFONTW *lfp,
+ gpointer dwrite_font,
gboolean is_synthetic)
{
LOGFONTW *lfp2 = NULL;
@@ -1690,7 +1697,11 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
PING (("not found"));
lfp2 = g_new (LOGFONTW, 1);
*lfp2 = *lfp;
+ if (dwrite_font == NULL)
+ dwrite_font = pango_win32_logfontw_get_dwrite_font (lfp2);
+
g_hash_table_insert (win32fontmap->fonts, lfp2, lfp2);
+ g_hash_table_insert (win32fontmap->dwrite_fonts, lfp2, dwrite_font);
description = pango_win32_font_description_from_logfontw (lfp2);
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index ffd247c1b..97bb6ba1d 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -99,6 +99,11 @@ struct _PangoWin32FontMap
*/
GHashTable *fonts;
+ /* Map LOGFONTWs to IDWriteFonts corresponding to actual fonts
+ * installed, if applicable.
+ */
+ GHashTable *dwrite_fonts;
+
/* keeps track of the system font aliases that we might have */
GHashTable *aliases;
@@ -284,12 +289,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);
+
PangoWin32DWriteItems *pango_win32_init_direct_write (void);
PangoWin32DWriteItems *pango_win32_get_direct_write_items (void);
+void pango_win32_dwrite_font_map_populate (PangoWin32FontMap *map);
+
void pango_win32_dwrite_items_destroy (PangoWin32DWriteItems *items);
+void pango_win32_dwrite_font_release (gpointer dwrite_font);
+
+gpointer pango_win32_logfontw_get_dwrite_font (LOGFONTW *logfontw);
+
G_END_DECLS
#endif /* __PANGOWIN32_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]