summaryrefslogtreecommitdiff
path: root/pango/pangowin32-dwrite-fontmap.cpp
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2022-07-21 14:53:42 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2022-09-26 11:04:25 +0800
commit902c839ab1725dac7e7a8a4ba2bf4b91c0cb1629 (patch)
treeac4f410447a58cbbc6c56b7d5e497daa85cc4b1e /pango/pangowin32-dwrite-fontmap.cpp
parentb406dd6e1282e7a98ed9a7b3d8b0e6af416a9797 (diff)
downloadpango-902c839ab1725dac7e7a8a4ba2bf4b91c0cb1629.tar.gz
PangoWin32: Implement is_hinted on Windows using DirectWrite
... by querying the font table 'gasp' and see whether the bits needed for hinting are there. Codewise, it is simpler with GDI+, but it would then require more overhead since GDI(+) operations are needed (this means "slower") and we need to put boilerplates for using GDI+ from our plain-C code.
Diffstat (limited to 'pango/pangowin32-dwrite-fontmap.cpp')
-rw-r--r--pango/pangowin32-dwrite-fontmap.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index ae1d11af..6be9b87a 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -420,6 +420,89 @@ pango_win32_font_description_from_logfontw_dwrite (const LOGFONTW *logfontw)
return desc;
}
+/* macros to help parse the 'gasp' font table, referring to FreeType2 */
+#define DWRITE_UCHAR_USHORT( p, i, s ) ( (unsigned short)( ((const unsigned char *)(p))[(i)] ) << (s) )
+
+#define DWRITE_PEEK_USHORT( p ) (unsigned short)( DWRITE_UCHAR_USHORT( p, 0, 8 ) | DWRITE_UCHAR_USHORT( p, 1, 0 ) )
+
+#define DWRITE_NEXT_USHORT( buffer ) ( (unsigned short)( buffer += 2, DWRITE_PEEK_USHORT( buffer - 2 ) ) )
+
+/* values to indicate that grid fit (hinting) is supported by the font */
+#define GASP_GRIDFIT 0x0001
+#define GASP_SYMMETRIC_GRIDFIT 0x0004
+
+gboolean
+pango_win32_dwrite_font_check_is_hinted (PangoWin32Font *font)
+{
+ IDWriteFont *dwrite_font = NULL;
+ IDWriteFontFace *dwrite_font_face = NULL;
+ gboolean failed = FALSE;
+ gboolean result = FALSE;
+ gboolean dwrite_font_release = FALSE;
+
+ gboolean succeeded = FALSE;
+ PangoWin32DWriteItems *dwrite_items = pango_win32_get_direct_write_items ();
+ dwrite_font = (IDWriteFont *) g_hash_table_lookup (PANGO_WIN32_FONT_MAP (font->fontmap)->dwrite_fonts,
+ &font->logfontw);
+
+ /* create the IDWriteFont from the logfont underlying the PangoWin32Font if needed */
+ if (dwrite_font == NULL)
+ {
+ if (FAILED (dwrite_items->gdi_interop->CreateFontFromLOGFONT (&font->logfontw,
+ &dwrite_font)) ||
+ dwrite_font == NULL)
+ failed = TRUE;
+ else
+ dwrite_font_release = TRUE;
+ }
+
+ if (!failed && SUCCEEDED (dwrite_font->CreateFontFace (&dwrite_font_face)) && dwrite_font_face != NULL)
+ {
+ UINT32 gasp_tag = DWRITE_MAKE_OPENTYPE_TAG ('g', 'a', 's', 'p');
+ UINT32 table_size;
+ const unsigned short *table_data;
+ void *table_ctx;
+ gboolean exists;
+
+ /* The 'gasp' table may not exist for the font, so no 'gasp' == no hinting */
+ if (SUCCEEDED (dwrite_font_face->TryGetFontTable (gasp_tag,
+ (const void **)(&table_data),
+ &table_size,
+ &table_ctx,
+ &exists)))
+ {
+ if (exists)
+ {
+ guint16 version = DWRITE_NEXT_USHORT (table_data);
+
+ if (version == 0 || version == 1)
+ {
+ guint16 num_ranges = DWRITE_NEXT_USHORT (table_data);
+ guint16 i;
+
+ for (i = 0; !result && i < num_ranges && i < (table_size / sizeof (guint16)); i ++)
+ {
+ guint16 ppem = DWRITE_NEXT_USHORT (table_data);
+ guint16 behavior = DWRITE_NEXT_USHORT (table_data);
+
+ if (behavior & (GASP_GRIDFIT | GASP_SYMMETRIC_GRIDFIT))
+ result = TRUE;
+ }
+ }
+ }
+
+ dwrite_font_face->ReleaseFontTable (table_ctx);
+ }
+
+ dwrite_font_face->Release ();
+ }
+
+ if (dwrite_font_release)
+ dwrite_font->Release ();
+
+ return result;
+}
+
void
pango_win32_dwrite_font_release (gpointer dwrite_font)
{