summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pango/meson.build1
-rw-r--r--pango/pangowin32-fontmap.c57
-rw-r--r--pango/pangowin32-private.h7
-rw-r--r--pango/pangowin32.c217
-rw-r--r--pango/pangowin32.h3
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__ */