summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-10-13 10:43:19 +0000
committerMatthias Clasen <mclasen@redhat.com>2022-10-13 10:43:19 +0000
commit3c947ecb260977724f2e53a3379df88b26713d1a (patch)
treea13f57bedf328e589cb1be95a4f9203aa0d7acb7
parent2541354d5c12ad4fa7c2e73c06f9b9bb21443f58 (diff)
parentcc488945cdbf58c0c69a21cd7ca07e8737271caf (diff)
downloadpango-3c947ecb260977724f2e53a3379df88b26713d1a.tar.gz
Merge branch 'pango1-dwrite' into 'main'
Pango-1.x: Add some DirectWrite support as a supplement See merge request GNOME/pango!635
-rw-r--r--meson.build27
-rw-r--r--pango/meson.build2
-rw-r--r--pango/pango-font-private.h4
-rw-r--r--pango/pangocairo-win32font.c27
-rw-r--r--pango/pangowin32-dwrite-fontmap.cpp590
-rw-r--r--pango/pangowin32-fontmap.c167
-rw-r--r--pango/pangowin32-private.h50
-rw-r--r--pango/pangowin32.c67
8 files changed, 828 insertions, 106 deletions
diff --git a/meson.build b/meson.build
index 8b14e38f..f63ce6cd 100644
--- a/meson.build
+++ b/meson.build
@@ -46,6 +46,7 @@ osx_current = pango_binary_age - pango_interface_age + 1
pango_osxversion = [osx_current, '@0@.@1@.0'.format(osx_current, pango_interface_age)]
cc = meson.get_compiler('c')
+cpp = meson.get_compiler('cpp')
host_system = host_machine.system()
# Compiler and linker flags
@@ -277,6 +278,24 @@ harfbuzz_dep = dependency('harfbuzz',
fallback: ['harfbuzz', 'libharfbuzz_dep'],
default_options: ['coretext=enabled'])
+if host_system == 'windows'
+ if cpp.has_header_symbol(
+ 'hb-directwrite.h',
+ 'hb_directwrite_face_create',
+ dependencies: harfbuzz_dep,
+ prefix: '#include <dwrite.h>',
+ )
+ pango_conf.set('HAVE_HARFBUZZ_DIRECT_WRITE', 1)
+ endif
+ if cc.has_header_symbol(
+ 'hb-gdi.h',
+ 'hb_gdi_face_create',
+ dependencies: harfbuzz_dep,
+ )
+ pango_conf.set('HAVE_HARFBUZZ_GDI', 1)
+ endif
+endif
+
pango_deps += harfbuzz_dep
# If option is 'auto' or 'enabled' it is not required to find fontconfig on the
@@ -390,9 +409,13 @@ endif
cairo_found_type = ''
cairo_dep = dependency('cairo', version: cairo_req_version, required: cairo_option)
+cairo_dwrite_dep = disabler() # Only for Windows
if cairo_dep.found()
cairo_found_type = cairo_dep.type_name()
+ if host_system == 'windows'
+ cairo_dwrite_dep = dependency('cairo-win32-dwrite-font', version: cairo_req_version, required: false)
+ endif
else
if cc.get_id() == 'msvc' and cc.has_header('cairo.h')
cairo_dep = cc.find_library('cairo', required: cairo_option)
@@ -566,6 +589,10 @@ if cairo_dep.found()
endif
endif
+if cairo_dwrite_dep.found()
+ pango_conf.set('HAVE_CAIRO_WIN32_DIRECTWRITE', 1)
+endif
+
# libsysprof-capture support
libsysprof_capture_dep = dependency('sysprof-capture-4',
required: get_option('sysprof'),
diff --git a/pango/meson.build b/pango/meson.build
index 1a4b4141..7d18cb00 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -424,11 +424,13 @@ if host_system == 'windows'
'pangowin32.c',
'pangowin32-fontcache.c',
'pangowin32-fontmap.c',
+ 'pangowin32-dwrite-fontmap.cpp',
]
pangowin32_deps = pango_deps + [
libpango_dep,
cc.find_library('gdi32'),
+ cc.find_library('dwrite'),
]
pangowin32_rc = configure_file(
diff --git a/pango/pango-font-private.h b/pango/pango-font-private.h
index e95abc7a..a77df662 100644
--- a/pango/pango-font-private.h
+++ b/pango/pango-font-private.h
@@ -61,7 +61,7 @@ void pango_font_get_matrix (PangoFont *font,
static inline int pango_font_get_absolute_size (PangoFont *font)
{
GTypeClass *klass = (GTypeClass *) PANGO_FONT_GET_CLASS (font);
- PangoFontClassPrivate *priv = g_type_class_get_private (klass, PANGO_TYPE_FONT);
+ PangoFontClassPrivate *priv = (PangoFontClassPrivate *) g_type_class_get_private (klass, PANGO_TYPE_FONT);
return priv->get_absolute_size (font);
}
@@ -69,7 +69,7 @@ static inline PangoVariant
pango_font_get_variant (PangoFont *font)
{
GTypeClass *klass = (GTypeClass *) PANGO_FONT_GET_CLASS (font);
- PangoFontClassPrivate *priv = g_type_class_get_private (klass, PANGO_TYPE_FONT);
+ PangoFontClassPrivate *priv = (PangoFontClassPrivate *) g_type_class_get_private (klass, PANGO_TYPE_FONT);
if (priv->get_variant)
return priv->get_variant (font);
else
diff --git a/pango/pangocairo-win32font.c b/pango/pangocairo-win32font.c
index 9f4f5c14..0141c414 100644
--- a/pango/pangocairo-win32font.c
+++ b/pango/pangocairo-win32font.c
@@ -75,6 +75,32 @@ pango_cairo_win32_font_create_font_face (PangoCairoFont *font)
{
PangoCairoWin32Font *cwfont = PANGO_CAIRO_WIN32_FONT (font);
PangoWin32Font *win32font = &cwfont->font;
+ void *dwrite_font_face = NULL;
+ gpointer dwrite_font = NULL;
+
+#ifdef HAVE_CAIRO_WIN32_DIRECTWRITE
+ dwrite_font_face = pango_win32_font_get_dwrite_font_face (win32font);
+ if (dwrite_font_face != NULL)
+ {
+ cairo_font_face_t *cairo_face = cairo_dwrite_font_face_create_for_dwrite_fontface (dwrite_font_face);
+
+ if (cairo_face != NULL)
+ {
+ static const cairo_user_data_key_t key;
+
+ cairo_font_face_set_user_data (cairo_face, &key,
+ dwrite_font_face,
+ (cairo_destroy_func_t) pango_win32_dwrite_font_face_release);
+
+ return cairo_face;
+ }
+ else
+ {
+ g_warning ("cairo_font_face creation failed with DirectWrite, fallback to GDI");
+ pango_win32_dwrite_font_face_release (dwrite_font_face);
+ }
+ }
+#endif
return cairo_win32_font_face_create_for_logfontw (&win32font->logfontw);
}
@@ -268,6 +294,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
new file mode 100644
index 00000000..6e1d9f0a
--- /dev/null
+++ b/pango/pangowin32-dwrite-fontmap.cpp
@@ -0,0 +1,590 @@
+/* Pango
+ * pangowin32-dwrite-fontmap.cpp: Win32 font handling with DirectWrite
+ *
+ * Copyright (C) 2022 Luca Bacci
+ * Copyright (C) 2022 Chun-wei Fan
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <initguid.h>
+#include <dwrite_1.h>
+
+#ifdef HAVE_HARFBUZZ_DIRECT_WRITE
+#include <hb-directwrite.h>
+#endif
+
+#ifdef STRICT
+#undef STRICT
+#endif
+#include "pangowin32-private.h"
+
+#ifdef _MSC_VER
+# define UUID_OF_IDWriteFactory __uuidof (IDWriteFactory)
+# define UUID_OF_IDWriteFont1 __uuidof (IDWriteFont1)
+#else
+# define UUID_OF_IDWriteFactory IID_IDWriteFactory
+# define UUID_OF_IDWriteFont1 IID_IDWriteFont1
+#endif
+
+struct _PangoWin32DWriteItems
+{
+ IDWriteFactory *dwrite_factory;
+ IDWriteGdiInterop *gdi_interop;
+};
+
+PangoWin32DWriteItems *
+pango_win32_init_direct_write (void)
+{
+ PangoWin32DWriteItems *dwrite_items = g_new0 (PangoWin32DWriteItems, 1);
+ HRESULT hr;
+ gboolean failed = FALSE;
+
+ hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,
+ UUID_OF_IDWriteFactory,
+ reinterpret_cast<IUnknown**> (&dwrite_items->dwrite_factory));
+
+ if (SUCCEEDED (hr) && dwrite_items->dwrite_factory != NULL)
+ {
+ hr = dwrite_items->dwrite_factory->GetGdiInterop (&dwrite_items->gdi_interop);
+ if (FAILED (hr) || dwrite_items->gdi_interop == NULL)
+ {
+ g_error ("DWriteCreateFactory::GetGdiInterop failed with error code %x", (unsigned)hr);
+ dwrite_items->dwrite_factory->Release ();
+ failed = TRUE;
+ }
+ }
+ else
+ {
+ g_error ("DWriteCreateFactory failed with error code %x", (unsigned)hr);
+ failed = TRUE;
+ }
+
+
+ if (failed)
+ g_free (dwrite_items);
+
+ return failed ? NULL : dwrite_items;
+}
+
+void
+pango_win32_dwrite_items_destroy (PangoWin32DWriteItems *dwrite_items)
+{
+ dwrite_items->gdi_interop->Release ();
+ dwrite_items->dwrite_factory->Release ();
+
+ g_free (dwrite_items);
+}
+
+static IDWriteFontFace *
+_pango_win32_get_dwrite_font_face_from_dwrite_font (IDWriteFont *font)
+{
+ IDWriteFontFace *face = NULL;
+ HRESULT hr;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ hr = font->CreateFontFace (&face);
+ if (SUCCEEDED (hr) && face != NULL)
+ return face;
+
+ g_warning ("IDWriteFont::CreateFontFace failed with error code %x\n", (unsigned)hr);
+ return NULL;
+}
+
+void *
+pango_win32_font_get_dwrite_font_face (PangoWin32Font *font)
+{
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
+ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (win32font->fontmap);
+ IDWriteFont *dwrite_font = NULL;
+ IDWriteFontFace *face = NULL;
+
+ dwrite_font = (IDWriteFont *) g_hash_table_lookup (win32fontmap->dwrite_fonts, &win32font->logfontw);
+
+ if (dwrite_font != NULL)
+ return (void *)_pango_win32_get_dwrite_font_face_from_dwrite_font (dwrite_font);
+
+ return NULL;
+}
+
+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;
+ }
+
+ face = _pango_win32_get_dwrite_font_face_from_dwrite_font (font);
+ if (face == NULL)
+ {
+ 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;
+}
+
+gboolean
+pango_win32_dwrite_font_is_monospace (gpointer dwrite_font,
+ gboolean *is_monospace)
+{
+ IDWriteFont *font = static_cast<IDWriteFont *>(dwrite_font);
+ IDWriteFont1 *font1 = NULL;
+ gboolean result = FALSE;
+
+ if (SUCCEEDED (font->QueryInterface(UUID_OF_IDWriteFont1,
+ reinterpret_cast<void**>(&font1))))
+ {
+ *is_monospace = font1->IsMonospacedFont ();
+ font1->Release ();
+ result = TRUE;
+ }
+ else
+ *is_monospace = FALSE;
+
+ 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;
+}
+
+static IDWriteFont *
+get_dwrite_font_from_pango_win32_font (PangoWin32Font *font,
+ gboolean *is_cleanup_dwrite_font)
+{
+ PangoWin32DWriteItems *dwrite_items = pango_win32_get_direct_write_items ();
+ IDWriteFont *dwrite_font = NULL;
+
+ 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 (SUCCEEDED (dwrite_items->gdi_interop->CreateFontFromLOGFONT (&font->logfontw,
+ &dwrite_font)) &&
+ dwrite_font != NULL)
+ *is_cleanup_dwrite_font = TRUE;
+ else
+ dwrite_font = NULL;
+ }
+
+ return dwrite_font;
+}
+
+/* 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;
+
+ dwrite_font_face = (IDWriteFontFace *)pango_win32_font_get_dwrite_font_face (font);
+
+ if (dwrite_font_face == NULL)
+ {
+ dwrite_font = get_dwrite_font_from_pango_win32_font (font, &dwrite_font_release);
+
+ if (dwrite_font != NULL)
+ dwrite_font_face = _pango_win32_get_dwrite_font_face_from_dwrite_font (dwrite_font);
+ else
+ {
+ g_warning ("Failed to retrieve IDWriteFont from PangoWin32Font");
+
+ return FALSE;
+ }
+ }
+
+ if (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;
+}
+
+#ifdef HAVE_HARFBUZZ_DIRECT_WRITE
+hb_face_t *
+pango_win32_dwrite_font_face_create_hb_face (gpointer face)
+{
+ return hb_directwrite_face_create ((IDWriteFontFace *)face);
+}
+#endif
+
+void
+pango_win32_dwrite_font_release (gpointer dwrite_font)
+{
+ IDWriteFont *font = static_cast<IDWriteFont *>(dwrite_font);
+
+ if (font != NULL)
+ font->Release ();
+}
+
+void
+pango_win32_dwrite_font_face_release (gpointer dwrite_font_face)
+{
+ IDWriteFontFace *face = static_cast<IDWriteFontFace *>(dwrite_font_face);
+
+ if (face != NULL)
+ face->Release ();
+}
diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c
index 9b980122..4cc95787 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,14 +709,18 @@ _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 ();
- win32fontmap->warned_fonts = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- 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 +730,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);
@@ -809,6 +810,7 @@ _pango_win32_font_map_class_init (PangoWin32FontMapClass *class)
(GEqualFunc)alias_equal,
(GDestroyNotify)alias_free,
NULL);
+
#ifdef HAVE_CAIRO_WIN32
read_windows_fallbacks (class->aliases);
read_builtin_aliases (class->aliases);
@@ -864,7 +866,7 @@ pango_win32_font_map_finalize (GObject *object)
pango_win32_font_cache_free (win32fontmap->font_cache);
- g_hash_table_destroy (win32fontmap->warned_fonts);
+ g_hash_table_destroy (win32fontmap->dwrite_fonts);
g_hash_table_destroy (win32fontmap->fonts);
g_hash_table_destroy (win32fontmap->families);
@@ -1145,6 +1147,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;
}
@@ -1193,6 +1196,8 @@ pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap,
return (PangoFont *)win32font;
}
+#if 0
+/* XXX: Add fallback for using GDI? */
static gboolean
_pango_win32_get_name_header (HDC hdc,
struct name_header *header)
@@ -1353,6 +1358,7 @@ get_family_nameA (const LOGFONTA *lfp)
fail0:
return g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
}
+#endif
/**
* pango_win32_font_description_from_logfont:
@@ -1376,6 +1382,34 @@ get_family_nameA (const LOGFONTA *lfp)
PangoFontDescription *
pango_win32_font_description_from_logfont (const LOGFONT *lfp)
{
+ LOGFONTW lfw;
+ PangoFontDescription *desc = NULL;
+ gchar *facename_utf8 = g_locale_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
+ wchar_t *facename_utf16 = g_utf8_to_utf16 (facename_utf8, -1, NULL, NULL, NULL);
+
+ lfw.lfHeight = lfp->lfHeight;
+ lfw.lfWidth = lfp->lfWidth;
+ lfw.lfEscapement = lfp->lfEscapement;
+ lfw.lfOrientation = lfp->lfOrientation;
+ lfw.lfWeight = lfp->lfWeight;
+ lfw.lfItalic = lfp->lfItalic;
+ lfw.lfUnderline = lfp->lfUnderline;
+ lfw.lfStrikeOut = lfp->lfStrikeOut;
+ lfw.lfCharSet = lfp->lfCharSet;
+ lfw.lfOutPrecision = lfp->lfOutPrecision;
+ lfw.lfClipPrecision = lfp->lfClipPrecision;
+ lfw.lfQuality = lfp->lfQuality;
+ lfw.lfPitchAndFamily = lfp->lfPitchAndFamily;
+ wcscpy (lfw.lfFaceName, facename_utf16);
+
+ desc = pango_win32_font_description_from_logfontw_dwrite (&lfw);
+ g_free (facename_utf16);
+ g_free (facename_utf8);
+
+ return desc;
+
+#if 0
+/* XXX: Add fallback for using GDI? */
PangoFontDescription *description;
gchar *family;
PangoStyle style;
@@ -1410,8 +1444,12 @@ pango_win32_font_description_from_logfont (const LOGFONT *lfp)
pango_font_description_set_variant (description, variant);
return description;
+#endif
}
+#if 0
+
+/* XXX: Add fallback for using GDI? */
static gchar *
get_family_nameW (const LOGFONTW *lfp)
{
@@ -1538,6 +1576,7 @@ get_family_nameW (const LOGFONTW *lfp)
fail0:
return g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL);
}
+#endif
/**
* pango_win32_font_description_from_logfontw:
@@ -1561,6 +1600,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;
@@ -1597,6 +1639,7 @@ pango_win32_font_description_from_logfontw (const LOGFONTW *lfp)
pango_font_description_set_variant (description, variant);
return description;
+#endif
}
static char *
@@ -1650,9 +1693,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;
@@ -1689,7 +1733,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);
@@ -1724,8 +1772,12 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap,
win32face->family = win32family =
pango_win32_get_font_family (win32fontmap,
pango_font_description_get_family (win32face->description));
- if ((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN)
- win32family->is_monospace = TRUE;
+
+ if (!pango_win32_dwrite_font_is_monospace (dwrite_font, &win32family->is_monospace))
+ {
+ if ((lfp->lfPitchAndFamily & 0xF0) == FF_MODERN)
+ win32family->is_monospace = TRUE;
+ }
win32family->faces = g_slist_append (win32family->faces, win32face);
@@ -1917,14 +1969,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);
@@ -1939,79 +1986,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 9102662a..f69d2b6b 100644
--- a/pango/pangowin32-private.h
+++ b/pango/pangowin32-private.h
@@ -57,6 +57,8 @@
#include "pango-fontset.h"
#include "pango-fontmap-private.h"
+G_BEGIN_DECLS
+
#define PANGO_TYPE_WIN32_FONT_MAP (_pango_win32_font_map_get_type ())
#define PANGO_WIN32_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT_MAP, PangoWin32FontMap))
#define PANGO_WIN32_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT_MAP))
@@ -73,6 +75,7 @@
typedef struct _PangoWin32FontMap PangoWin32FontMap;
typedef struct _PangoWin32FontMapClass PangoWin32FontMapClass;
+typedef struct _PangoWin32DWriteItems PangoWin32DWriteItems;
typedef struct _PangoWin32Font PangoWin32Font;
typedef struct _PangoWin32FontClass PangoWin32FontClass;
typedef struct _PangoWin32Face PangoWin32Face;
@@ -96,12 +99,14 @@ 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;
- /* keeps track of the warned fonts that we might have */
- GHashTable *warned_fonts;
-
double resolution; /* (points / pixel) * PANGO_SCALE */
};
@@ -137,6 +142,9 @@ struct _PangoWin32Font
*/
gboolean in_cache;
GHashTable *glyph_info;
+
+ /* whether the font supports hinting */
+ gboolean is_hinted;
};
struct _PangoWin32FontClass
@@ -279,6 +287,42 @@ _PANGO_EXTERN
gpointer _pango_win32_copy_cmap (gpointer cmap,
guint16 cmap_format);
+_PANGO_EXTERN
+gboolean pango_win32_dwrite_font_check_is_hinted (PangoWin32Font *font);
+
+_PANGO_EXTERN
+void *pango_win32_font_get_dwrite_font_face (PangoWin32Font *font);
+
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);
+
+gboolean pango_win32_dwrite_font_is_monospace (gpointer dwrite_font,
+ gboolean *is_monospace);
+
+void pango_win32_dwrite_font_release (gpointer dwrite_font);
+
+_PANGO_EXTERN
+void pango_win32_dwrite_font_face_release (gpointer dwrite_font_face);
+
+gpointer pango_win32_logfontw_get_dwrite_font (LOGFONTW *logfontw);
+
+PangoFontDescription *
+pango_win32_font_description_from_logfontw_dwrite (const LOGFONTW *logfontw);
+
+hb_face_t *pango_win32_dwrite_font_face_create_hb_face (gpointer face);
+
+G_END_DECLS
+
#endif /* __PANGOWIN32_PRIVATE_H__ */
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index eed92dde..09b97a55 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -29,6 +29,10 @@
#include <glib.h>
#include <hb.h>
+#if defined (HAVE_HARFBUZZ_GDI)
+#include <hb-gdi.h>
+#endif
+
#include "pango-impl-utils.h"
#include "pangowin32.h"
#include "pangowin32-private.h"
@@ -56,6 +60,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,
@@ -126,11 +131,13 @@ _pango_win32_font_init (PangoWin32Font *win32font)
}
static GPrivate display_dc_key = G_PRIVATE_INIT ((GDestroyNotify) DeleteDC);
+static GPrivate dwrite_items = G_PRIVATE_INIT ((GDestroyNotify) pango_win32_dwrite_items_destroy);
HDC
_pango_win32_get_display_dc (void)
{
HDC hdc = g_private_get (&display_dc_key);
+ PangoWin32DWriteItems *items;
if (hdc == NULL)
{
@@ -151,9 +158,22 @@ _pango_win32_get_display_dc (void)
#endif
}
+ items = g_private_get (&dwrite_items);
+ if (items == NULL)
+ {
+ items = pango_win32_init_direct_write ();
+ g_private_set (&dwrite_items, items);
+ }
+
return hdc;
}
+PangoWin32DWriteItems *
+pango_win32_get_direct_write_items (void)
+{
+ return g_private_get (&dwrite_items);
+}
+
/**
* pango_win32_get_dc:
*
@@ -187,6 +207,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;
@@ -203,6 +224,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 ();
}
@@ -647,6 +671,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
@@ -1257,20 +1289,45 @@ hfont_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
static hb_font_t *
pango_win32_font_create_hb_font (PangoFont *font)
{
- PangoWin32Font *win32font = (PangoWin32Font *)font;
- HFONT hfont;
+ PangoWin32Font *win32font = PANGO_WIN32_FONT (font);
+ HFONT hfont = NULL;
hb_face_t *face = NULL;
hb_font_t *hb_font = NULL;
+ static const hb_user_data_key_t key;
+ hb_destroy_func_t destroy_func = NULL;
+ void *destroy_obj = NULL;
+ gpointer dwrite_font_face = NULL;
g_return_val_if_fail (font != NULL, NULL);
- hfont = _pango_win32_font_get_hfont (font);
+#ifdef HAVE_HARFBUZZ_DIRECT_WRITE
+ dwrite_font_face = pango_win32_font_get_dwrite_font_face (win32font);
+
+ if (dwrite_font_face != NULL)
+ {
+ face = pango_win32_dwrite_font_face_create_hb_face (dwrite_font_face);
+ destroy_func = pango_win32_dwrite_font_face_release;
+ destroy_obj = dwrite_font_face;
+ }
+#endif
+ if (face == NULL)
+ {
+ hfont = _pango_win32_font_get_hfont (font);
- /* We are *not* allowed to destroy the HFONT here ! */
- face = hb_face_create_for_tables (hfont_reference_table, (void *)hfont, NULL);
+#ifdef HAVE_HARFBUZZ_GDI
+ face = hb_gdi_face_create (hfont);
+#else
+ face = hb_face_create_for_tables (hfont_reference_table, (void *)hfont, NULL);
+#endif
+ }
hb_font = hb_font_create (face);
hb_font_set_scale (hb_font, win32font->size, win32font->size);
+
+ /* We are supposed to destroy the IDWriteFontFace, but *not* the HFONT! */
+ if (destroy_func != NULL && destroy_obj != NULL)
+ hb_font_set_user_data (hb_font, &key, destroy_obj, destroy_func, TRUE);
+
hb_face_destroy (face);
return hb_font;