summaryrefslogtreecommitdiff
path: root/pango/pangowin32.c
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2020-11-11 20:15:25 +0800
committerChun-wei Fan <fanchunwei@src.gnome.org>2020-12-03 18:53:40 +0800
commit497ee87d5105fb3b6a957abdaf4754ab1d6c6533 (patch)
tree1cdb5930ef0f942e8936f0a57b51e6314820ad26 /pango/pangowin32.c
parent66e2ea5f428893e102fe2cbaa45de0852118f5e2 (diff)
downloadpango-497ee87d5105fb3b6a957abdaf4754ab1d6c6533.tar.gz
PangoWin32: Initialize DirectWrite as wellwin32-font-language
We want to start using DirectWrite to help us implement some features that are not that easily done with GDI/Uniscribe, via a GDI interop layer as provided by DirectWrite, and by creating and keeping track of the IDWriteFont's that are created from each of the LOGFONTs that we acquire by quering the fonts that is installed on the system.
Diffstat (limited to 'pango/pangowin32.c')
-rw-r--r--pango/pangowin32.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 7904c96d..8263c27b 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -32,6 +32,8 @@
*/
#include "config.h"
+#include <initguid.h>
+
#include <string.h>
#include <stdlib.h>
#include <glib.h>
@@ -133,7 +135,30 @@ _pango_win32_font_init (PangoWin32Font *win32font)
win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free);
}
+typedef struct dwrite_init_items
+{
+ IDWriteFactory *factory;
+ IDWriteGdiInterop *gdi_interop;
+ GHashTable *ht_script_language;
+} dwrite_items;
+
+static void
+ShutdownDWrite (dwrite_items *items)
+{
+ if (items->ht_script_language != NULL)
+ g_hash_table_destroy (items->ht_script_language);
+
+ if (items->gdi_interop != NULL)
+ IDWriteGdiInterop_Release (items->gdi_interop);
+
+ if (items->factory != NULL)
+ IDWriteFactory_Release (items->factory);
+
+ g_free (items);
+}
+
static GPrivate display_dc_key = G_PRIVATE_INIT ((GDestroyNotify) DeleteDC);
+static GPrivate dwrite_items_key = G_PRIVATE_INIT ((GDestroyNotify) ShutdownDWrite);
HDC
_pango_win32_get_display_dc (void)
@@ -190,6 +215,130 @@ pango_win32_get_debug_flag (void)
return _pango_win32_debug;
}
+static BOOL CALLBACK
+get_available_scripts_for_locales (wchar_t *locale,
+ DWORD flags,
+ LPARAM *data)
+{
+ GHashTable *ht_script_language = (GHashTable *)data;
+ wchar_t *scripts_w;
+ gchar *scripts_raw;
+ gchar **scripts_array;
+ int sz, i;
+ GSList *locale_list;
+
+ sz = GetLocaleInfoEx (locale, LOCALE_SSCRIPTS, NULL, 0);
+
+ if (sz == 0)
+ return FALSE;
+
+ scripts_w = g_new (wchar_t, sz);
+
+ if (GetLocaleInfoEx (locale, LOCALE_SSCRIPTS, scripts_w, sz) == 0)
+ {
+ g_free (scripts_w);
+ return FALSE;
+ }
+
+ scripts_raw = g_utf16_to_utf8 (scripts_w, -1, NULL, NULL, NULL);
+
+ scripts_array = g_strsplit_set (scripts_raw, ";", -1);
+
+ for (i = 0; scripts_array[i] != NULL; i ++)
+ {
+ if (g_ascii_strcasecmp ("", scripts_array[i]) != 0)
+ {
+ g_hash_table_steal_extended (ht_script_language, scripts_array[i], NULL, (void **)&locale_list);
+ locale_list = g_slist_prepend (locale_list, g_utf16_to_utf8 (locale, -1, NULL, NULL, NULL));
+ g_hash_table_replace (ht_script_language, scripts_array[i], locale_list);
+ }
+ }
+
+ g_free (scripts_w);
+ return TRUE;
+}
+
+static void
+remove_language_list (GSList *list)
+{
+ g_slist_free_full (list, g_free);
+}
+
+static dwrite_items *
+_pango_win32_setup_dwrite (void)
+{
+ dwrite_items *items = NULL;
+ IDWriteGdiInterop *dwrite_gdi = NULL;
+
+ items = g_private_get (&dwrite_items_key);
+
+ if (items == NULL)
+ {
+ gboolean failed = FALSE;
+ items = g_new0 (dwrite_items, 1);
+
+ if (DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,
+ &IID_IDWriteFactory,
+ (IUnknown **)&items->factory) != S_OK)
+ {
+ g_warning ("DWrite factory creation failed!");
+ failed = TRUE;
+ }
+ else
+ {
+ if (IDWriteFactory_GetGdiInterop (items->factory,
+ &items->gdi_interop) != S_OK)
+ {
+ g_warning ("DWrite GDI interop creation failed!");
+ failed = TRUE;
+ }
+ else
+ {
+ items->ht_script_language = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ remove_language_list);
+
+ if (!EnumSystemLocalesEx (get_available_scripts_for_locales,
+ LOCALE_ALL,
+ (LPARAM)items->ht_script_language,
+ NULL))
+ {
+ gchar *syserr = g_win32_error_message (GetLastError ());
+
+ g_warning ("Failed to enumerate system locales, error: %s!", syserr);
+ g_free (syserr);
+ failed = TRUE;
+ }
+ else
+ g_private_set (&dwrite_items_key, items);
+ }
+ }
+
+ if (failed)
+ {
+ ShutdownDWrite (items);
+ items = NULL;
+ }
+ }
+
+ return items;
+}
+
+IDWriteGdiInterop *
+_pango_win32_acquire_dwrite_gdi_interop (void)
+{
+ dwrite_items *items = _pango_win32_setup_dwrite ();
+ return items->gdi_interop;
+}
+
+GHashTable *
+_pango_win32_acquire_script_locale_ht (void)
+{
+ dwrite_items *items = _pango_win32_setup_dwrite ();
+ return items->ht_script_language;
+}
+
static void
_pango_win32_font_class_init (PangoWin32FontClass *class)
{
@@ -212,6 +361,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
class->get_metrics_factor = pango_win32_font_real_get_metrics_factor;
_pango_win32_get_display_dc ();
+ _pango_win32_setup_dwrite ();
}
/**
@@ -1288,3 +1438,70 @@ GType pango_win32_font_get_type (void)
{
return _pango_win32_font_get_type ();
}
+
+PangoLanguage **
+pango_win32_font_get_languages (PangoFont *font)
+{
+ PangoWin32Font *win32font = NULL;
+ IDWriteGdiInterop *gdi_interop = NULL;
+ IDWriteFont *dwritefont = NULL;
+ IDWriteLocalizedStrings *dwrite_result_str;
+ gboolean exists = FALSE;
+ LOGFONTW lf = win32font->logfontw;
+ PangoLanguage **langs = NULL;
+
+ g_return_val_if_fail (font != NULL, NULL);
+ g_return_val_if_fail (PANGO_IS_WIN32_FONT (font), NULL);
+
+ win32font = PANGO_WIN32_FONT (font);
+ gdi_interop = _pango_win32_acquire_dwrite_gdi_interop ();
+
+ if (IDWriteGdiInterop_CreateFontFromLOGFONT (gdi_interop,
+ &lf,
+ &dwritefont) != S_OK)
+ g_warning ("Faild to create DirectWriteFont from LOGFONTW");
+
+ if (IDWriteFont_GetInformationalStrings (dwritefont,
+ DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG,
+ &dwrite_result_str,
+ &exists) != S_OK)
+ {
+ gchar *name = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
+ g_warning ("Failed to get supported languages of font %p (name: %s)", &lf, name);
+ g_free (name);
+ }
+
+ if (exists)
+ {
+ gchar *name = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
+ guint num_langs = IDWriteLocalizedStrings_GetCount (dwrite_result_str);
+ guint i = 0;
+ GHashTable *ht_script_language = _pango_win32_acquire_script_locale_ht();
+
+ for (i = 0; i < num_langs; i ++)
+ {
+ guint strlength = 0;
+ wchar_t *str_utf16 = NULL;
+ gchar *str_utf8 = NULL;
+ GSList *langs = NULL;
+ IDWriteLocalizedStrings_GetStringLength (dwrite_result_str, i, &strlength);
+ str_utf16 = g_new0 (wchar_t, strlength + 1);
+ IDWriteLocalizedStrings_GetString (dwrite_result_str, i, str_utf16, strlength + 1);
+ str_utf8 = g_utf16_to_utf8 (str_utf16, -1, NULL, NULL, NULL);
+ langs = g_hash_table_lookup (ht_script_language, str_utf8);
+ if (langs != NULL)
+ {
+ GSList *p;
+
+ for (p = g_slist_reverse (langs); p != NULL; p = p->next)
+ if (pango_language_from_string (p->data) == NULL)
+ g_print ("NULL!\n");
+ }
+ g_free (str_utf8);
+ g_free (str_utf16);
+ }
+ g_free (name);
+ }
+
+ return langs;
+}