[pango/pango1-dwrite] PangoWin32: Implement is_hinted on Windows using DirectWrite
- From: Chun-wei Fan <fanchunwei src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/pango1-dwrite] PangoWin32: Implement is_hinted on Windows using DirectWrite
- Date: Fri, 22 Jul 2022 08:11:57 +0000 (UTC)
commit c8953ceeabc62b64138b506f2ba2ba8eb14f27ff
Author: Chun-wei Fan <fanchunwei src gnome org>
Date: Thu Jul 21 14:53:42 2022 +0800
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.
pango/pangocairo-win32font.c | 1 +
pango/pangowin32-dwrite-fontmap.cpp | 83 +++++++++++++++++++++++++++++++++++++
pango/pangowin32-fontmap.c | 1 +
pango/pangowin32-private.h | 6 +++
pango/pangowin32.c | 13 ++++++
5 files changed, 104 insertions(+)
---
diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c
index 9f4f5c140..5b860bab8 100644
--- a/pango/pangocairo-win32font.c
+++ b/pango/pangocairo-win32font.c
@@ -268,6 +268,7 @@ _pango_cairo_win32_font_new (PangoCairoWin32FontMap *cwfontmap,
win32font->size,
&win32font->logfontw);
+ win32font->is_hinted = pango_win32_dwrite_font_check_is_hinted (win32font);
cairo_matrix_init_identity (&font_matrix);
cairo_matrix_scale (&font_matrix, size, size);
diff --git a/pango/pangowin32-dwrite-fontmap.cpp b/pango/pangowin32-dwrite-fontmap.cpp
index 2d83eafe4..916891c7f 100644
--- a/pango/pangowin32-dwrite-fontmap.cpp
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -422,6 +422,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)
{
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index 627b24efc..836a3e465 100644
--- a/pango/pangowin32-fontmap.c
+++ b/pango/pangowin32-fontmap.c
@@ -1152,6 +1152,7 @@ pango_win32_font_neww (PangoFontMap *fontmap,
result->size = size;
_pango_win32_make_matching_logfontw (fontmap, lfp, size, &result->logfontw);
+ result->is_hinted = pango_win32_dwrite_font_check_is_hinted (result);
return result;
}
diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h
index b8ade516f..db2eb5042 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -145,6 +145,9 @@ struct _PangoWin32Font
*/
gboolean in_cache;
GHashTable *glyph_info;
+
+ /* whether the font supports hinting */
+ gboolean is_hinted;
};
struct _PangoWin32FontClass
@@ -287,6 +290,9 @@ _PANGO_EXTERN
gpointer _pango_win32_copy_cmap (gpointer cmap,
guint16 cmap_format);
+_PANGO_EXTERN
+gboolean pango_win32_dwrite_font_check_is_hinted (PangoWin32Font *font);
+
extern gboolean _pango_win32_debug;
void pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 55a079c9f..5a26ee98b 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -56,6 +56,7 @@ static gboolean pango_win32_font_real_select_font (PangoFont *font,
HDC hdc);
static void pango_win32_font_real_done_font (PangoFont *font);
static double pango_win32_font_real_get_metrics_factor (PangoFont *font);
+static gboolean pango_win32_font_is_hinted (PangoFont *font);
static void pango_win32_get_item_properties (PangoItem *item,
PangoUnderline *uline,
@@ -202,6 +203,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoFontClassPrivate *pclass;
object_class->finalize = pango_win32_font_finalize;
object_class->dispose = pango_win32_font_dispose;
@@ -218,6 +220,9 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
class->done_font = pango_win32_font_real_done_font;
class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
+ pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT);
+ pclass->is_hinted = pango_win32_font_is_hinted;
+
_pango_win32_get_display_dc ();
}
@@ -662,6 +667,14 @@ pango_win32_font_real_get_metrics_factor (PangoFont *font)
return PANGO_SCALE;
}
+static gboolean
+pango_win32_font_is_hinted (PangoFont *font)
+{
+ g_return_val_if_fail (PANGO_WIN32_IS_FONT (font), FALSE);
+
+ return PANGO_WIN32_FONT (font)->is_hinted;
+}
+
/**
* pango_win32_font_logfont:
* @font: a `PangoFont` which must be from the Win32 backend
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]