diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/meson.build | 1 | ||||
-rw-r--r-- | pango/pangowin32-fontmap.c | 57 | ||||
-rw-r--r-- | pango/pangowin32-private.h | 7 | ||||
-rw-r--r-- | pango/pangowin32.c | 217 | ||||
-rw-r--r-- | pango/pangowin32.h | 3 |
5 files changed, 285 insertions, 0 deletions
diff --git a/pango/meson.build b/pango/meson.build index 91261274..21b620ec 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -413,6 +413,7 @@ if host_system == 'windows' pangowin32_deps = pango_deps + [ libpango_dep, cc.find_library('gdi32'), + cc.find_library('dwrite'), ] pangowin32_rc = configure_file( diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index 6bc10a7a..23902981 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -1588,12 +1588,19 @@ ff_name (int ff, char* num) } } +/* remove later... */ +extern GHashTable * +_pango_win32_acquire_script_locale_ht (void); + static void pango_win32_insert_font (PangoWin32FontMap *win32fontmap, LOGFONTW *lfp, gboolean is_synthetic) { LOGFONTW *lfp2 = NULL; + IDWriteGdiInterop *gdi_interop = _pango_win32_acquire_dwrite_gdi_interop (); + IDWriteLocalizedStrings *dwrite_result_str; + gboolean exists = FALSE; PangoFontDescription *description; PangoWin32Family *win32family; PangoWin32Face *win32face; @@ -1645,6 +1652,12 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, PING (("win32face created: %p for %S", win32face, lfp->lfFaceName)); win32face->logfontw = *lfp; + + if (IDWriteGdiInterop_CreateFontFromLOGFONT (gdi_interop, + &win32face->logfontw, + &win32face->dwrite_font) != S_OK) + g_warning ("Failed to create DirectWriteFont from LOGFONTW"); + win32face->description = description; win32face->coverage = NULL; @@ -1667,6 +1680,48 @@ pango_win32_insert_font (PangoWin32FontMap *win32fontmap, win32family->faces = g_slist_append (win32family->faces, win32face); + if (IDWriteFont_GetInformationalStrings (win32face->dwrite_font, + DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG, + &dwrite_result_str, + &exists) != S_OK) + { + gchar *name = g_utf16_to_utf8 (lfp->lfFaceName, -1, NULL, NULL, NULL); + g_warning ("Failed to get supported languages of font %p (name: %s)", lfp, name); + g_free (name); + } + + if (exists) + { + gchar *name = g_utf16_to_utf8 (lfp->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); + } + PING (("name=%s, length(faces)=%d", win32family->family_name, g_slist_length (win32family->faces))); } @@ -1763,6 +1818,8 @@ pango_win32_face_finalize (GObject *object) g_slist_free (win32face->cached_fonts); // g_slist_free_full (win32face->cached_fonts, g_object_unref); // This doesn't work. + if (win32face->dwrite_font != NULL) + IDWriteFont_Release (win32face->dwrite_font); G_OBJECT_CLASS (pango_win32_family_parent_class)->finalize (object); } diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h index 9ea00dbc..da957091 100644 --- a/pango/pangowin32-private.h +++ b/pango/pangowin32-private.h @@ -52,6 +52,10 @@ #define PING(printlist) #endif +/* this is a C-compatible counterpart of the DirectWrite headers */ +#define COBJMACROS +#include "dwrite_c.h" + #include "pangowin32.h" #include "pango-font-private.h" #include "pango-fontset-private.h" @@ -152,6 +156,7 @@ struct _PangoWin32Face gpointer family; LOGFONTW logfontw; + IDWriteFont *dwrite_font; PangoFontDescription *description; PangoCoverage *coverage; char *face_name; @@ -274,4 +279,6 @@ HDC _pango_win32_get_display_dc (void); extern gboolean _pango_win32_debug; +IDWriteGdiInterop * _pango_win32_acquire_dwrite_gdi_interop (void); + #endif /* __PANGOWIN32_PRIVATE_H__ */ 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; +} diff --git a/pango/pangowin32.h b/pango/pangowin32.h index fe68cc31..c48f0cdf 100644 --- a/pango/pangowin32.h +++ b/pango/pangowin32.h @@ -153,6 +153,9 @@ PangoFontDescription *pango_win32_font_description_from_logfontw (const LOGFONTW PANGO_AVAILABLE_IN_1_48 GType pango_win32_font_get_type (void) G_GNUC_CONST; +PANGO_AVAILABLE_IN_1_48 +PangoLanguage **pango_win32_font_get_languages (PangoFont *font); + G_END_DECLS #endif /* __PANGOWIN32_H__ */ |