[gtk/wip/fanc999/fontchooser.win32: 32/32] wip: Enable OpenType Font Details without using PangoFT on Windows



commit 2af656ace9d9786da21e7ad1b3aa91762cd7a386
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Thu Jun 28 17:48:25 2018 +0800

    wip: Enable OpenType Font Details without using PangoFT on Windows
    
    The current implementation of the font tweaking widget assumes that we
    are using PangoFT2, which means that we need to have FontConfig around,
    and we need to explicitly set the PangoCairo backend to be "fc" for it
    to work; otherwise anything using it on Windows will crash because we
    are using PangoWin32 instead.
    
    This is a quick port for PangoWin32 which retrieves the LOGFONTW from
    the PangoFont that we are using, and makes use of DirectWrite with GDI
    interoperability to obtain the raw data to the font file(s) that we
    are dealing with each font, so that we can continue on to create the
    FT_Face that we need to feed to HarfBuzz so that we can use it to read
    the font tables for us.  The reasoning behind using DirectWrite here is
    also to prepare for the eventual transition to it, as there are now
    features that could make use of it, such as colored font, on native
    Windows, as opposed to just using GDI and Uniscribe.
    
    This port still makes use of FreeType and HarfBuzz, but this work
    attempts to simplify the depedencies involved by requiring only the
    FreeType libraries (which we can build without much issue on Windows
    using their Visual Studio projects and/or CMake build files) and
    HarfBuzz that is built with FreeType support (which can be built using
    CMake as well).  FontConfig will not be required for this port, as
    FontConfig can be cumbersome to set up and build on Windows.
    
    This will also remove the need to xml-codes when the code is built for
    Windows, regardless of whether the PangoWin32 or PangoFT2 is used.
    
    A full native DirectWrite port could be possible, but that will likely
    involve much more addition to the code, which might not be that
    feasible, especially with differences on how the details on how
    DirectWrite works on older Windows (7, 8, 8.1) and the different
    releases of Windows 10.
    
    This is still WIP, as we need to do the actual tweaking of the fonts
    where that is supported.

 demos/gtk-demo/font_features.c | 121 ++++++++--
 demos/gtk-demo/meson.build     |  11 +-
 gdk/win32/gdkdisplay-win32.c   | 511 +++++++++++++++++++++++++++++++++++++++++
 gdk/win32/gdkdisplay-win32.h   |  16 ++
 gdk/win32/gdkwin32misc.h       |  18 ++
 gtk/gtkfontchooserwidget.c     | 163 +++++++++++--
 gtk/meson.build                |  19 +-
 meson.build                    |  21 +-
 8 files changed, 834 insertions(+), 46 deletions(-)
---
diff --git a/demos/gtk-demo/font_features.c b/demos/gtk-demo/font_features.c
index 5e639576f0..66165b05fb 100644
--- a/demos/gtk-demo/font_features.c
+++ b/demos/gtk-demo/font_features.c
@@ -11,14 +11,40 @@
  * axes are also offered for customization.
  */
 
+#include "config.h"
+
+#define GTK_DEMO_FONT_FEATURES
+
 #include <gtk/gtk.h>
-#include <pango/pangofc-font.h>
+
+#ifdef HAVE_PANGOFT
+# include <pango/pangofc-font.h>
+#endif
+
+#ifdef GDK_WINDOWING_WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <pango/pangowin32.h>
+# include "gdk/win32/gdkwin32.h"
+
+extern GType _pango_win32_font_get_type (void) G_GNUC_CONST;
+
+#define PANGO_TYPE_WIN32_FONT            (_pango_win32_font_get_type ())
+#define PANGO_WIN32_FONT(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT, 
PangoWin32Font))
+#define PANGO_WIN32_FONT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+#define PANGO_WIN32_IS_FONT(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT))
+#define PANGO_WIN32_FONT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+#endif
+
 #include <hb.h>
 #include <hb-ot.h>
+
 #include <hb-ft.h>
 #include <freetype/ftmm.h>
 #include <freetype/ftsnames.h>
 #include <freetype/ttnameid.h>
+
 #include <glib/gi18n.h>
 
 #include "open-type-layout.h"
@@ -26,6 +52,10 @@
 #include "script-names.h"
 #include "language-names.h"
 
+#ifdef GDK_WINDOWING_WIN32
+extern GHashTable *gtk_font_chooser_widget_get_win32_locales (void);
+#endif
+
 
 #define MAKE_TAG(a,b,c,d) (unsigned int)(((a) << 24) | ((b) << 16) | ((c) <<  8) | (d))
 
@@ -439,12 +469,12 @@ typedef struct {
   hb_tag_t lang_tag;
   unsigned int script_index;
   unsigned int lang_index;
-} TagPair;
+} TagPairHB;
 
 static guint
 tag_pair_hash (gconstpointer data)
 {
-  const TagPair *pair = data;
+  const TagPairHB *pair = data;
 
   return pair->script_tag + pair->lang_tag;
 }
@@ -452,8 +482,8 @@ tag_pair_hash (gconstpointer data)
 static gboolean
 tag_pair_equal (gconstpointer a, gconstpointer b)
 {
-  const TagPair *pair_a = a;
-  const TagPair *pair_b = b;
+  const TagPairHB *pair_a = a;
+  const TagPairHB *pair_b = b;
 
   return pair_a->script_tag == pair_b->script_tag && pair_a->lang_tag == pair_b->lang_tag;
 }
@@ -484,15 +514,19 @@ update_script_combo (void)
   GtkListStore *store;
   hb_font_t *hb_font;
   gint i, j, k;
-  FT_Face ft_face;
   PangoFont *pango_font;
   GHashTable *tags;
   GHashTableIter iter;
-  TagPair *pair;
   char *lang;
   hb_tag_t active;
   GtkTreeIter active_iter;
   gboolean have_active = FALSE;
+  gboolean use_pango_fc = FALSE;
+  gboolean use_pango_win32 = FALSE;
+
+  FT_Face ft_face;
+  FT_Byte *font_file_data = NULL;
+  TagPairHB *pair;
 
   lang = gtk_font_chooser_get_language (GTK_FONT_CHOOSER (font));
   active = hb_ot_tag_from_language (hb_language_from_string (lang, -1));
@@ -501,12 +535,22 @@ update_script_combo (void)
   store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
 
   pango_font = get_pango_font ();
-  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (PANGO_WIN32_IS_FONT (pango_font))
+    ft_face = gdk_win32_get_ft_face_from_pango_font (gtk_widget_get_display (GTK_WIDGET (font)),
+                                                     pango_font);
+#endif
+
   hb_font = hb_ft_font_create (ft_face, NULL);
 
   tags = g_hash_table_new_full (tag_pair_hash, tag_pair_equal, g_free, NULL);
 
-  pair = g_new (TagPair, 1);
+  pair = g_new (TagPairHB, 1);
   pair->script_tag = HB_OT_TAG_DEFAULT_SCRIPT;
   pair->lang_tag = HB_OT_TAG_DEFAULT_LANGUAGE;
   g_hash_table_add (tags, pair);
@@ -528,11 +572,10 @@ update_script_combo (void)
             {
               hb_tag_t languages[80];
               unsigned int language_count = G_N_ELEMENTS (languages);
-
               hb_ot_layout_script_get_language_tags (hb_face, tables[i], j, 0, &language_count, languages);
               for (k = 0; k < language_count; k++)
                 {
-                  pair = g_new (TagPair, 1);
+                  pair = g_new (TagPairHB, 1);
                   pair->script_tag = scripts[j];
                   pair->lang_tag = languages[k];
                   pair->script_index = j;
@@ -545,7 +588,11 @@ update_script_combo (void)
       hb_face_destroy (hb_face);
     }
 
-  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#endif
+
   g_object_unref (pango_font);
 
   g_hash_table_iter_init (&iter, tags);
@@ -557,9 +604,19 @@ update_script_combo (void)
 
       if (pair->lang_tag == HB_OT_TAG_DEFAULT_LANGUAGE)
         langname = NC_("Language", "Default");
+
       else
         {
+#ifdef GDK_WINDOWING_WIN32
+          GHashTable *ht_win32_languages = NULL;
+          hb_language_t lang;
+
+          ht_win32_languages = gtk_font_chooser_widget_get_win32_locales ();
+          lang = hb_ot_tag_to_language (pair->lang_tag);
+          langname = g_hash_table_lookup (ht_win32_languages, lang);
+#else
           langname = get_language_name_for_tag (pair->lang_tag);
+#endif
           if (!langname)
             {
               hb_tag_to_string (pair->lang_tag, langbuf);
@@ -603,9 +660,10 @@ update_features (void)
   GtkTreeIter iter;
   guint script_index, lang_index;
   PangoFont *pango_font;
-  FT_Face ft_face;
   hb_font_t *hb_font;
   GList *l;
+  FT_Face ft_face;
+  FT_Byte *font_file_data = NULL;
 
   for (l = feature_items; l; l = l->next)
     {
@@ -628,7 +686,17 @@ update_features (void)
                       -1);
 
   pango_font = get_pango_font ();
-  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (PANGO_WIN32_IS_FONT (pango_font))
+    ft_face = gdk_win32_get_ft_face_from_pango_font (gtk_widget_get_display (GTK_WIDGET (font)),
+                                                     pango_font);
+#endif
+
   hb_font = hb_ft_font_create (ft_face, NULL);
 
   if (hb_font)
@@ -715,7 +783,11 @@ update_features (void)
       hb_face_destroy (hb_face);
     }
 
-  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#endif
+
   g_object_unref (pango_font);
 }
 
@@ -1516,9 +1588,11 @@ update_font_variations (void)
 {
   GtkWidget *child, *next;
   PangoFont *pango_font;
+
   FT_Face ft_face;
   FT_MM_Var *ft_mm_var;
   FT_Error ret;
+  FT_Byte *font_file_data = NULL;
 
   child = gtk_widget_get_first_child (variations_grid);
   while (child != NULL)
@@ -1534,7 +1608,16 @@ update_font_variations (void)
   g_hash_table_remove_all (instances);
 
   pango_font = get_pango_font ();
-  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (PANGO_WIN32_IS_FONT (pango_font))
+    ft_face = gdk_win32_get_ft_face_from_pango_font (gtk_widget_get_display (GTK_WIDGET (font)),
+                                                     pango_font);
+#endif
 
   ret = FT_Get_MM_Var (ft_face, &ft_mm_var);
   if (ret == 0)
@@ -1588,7 +1671,11 @@ update_font_variations (void)
       free (ft_mm_var);
     }
 
-  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#endif
+
   g_object_unref (pango_font);
 }
 
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 93c2902575..5d402f4353 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -78,10 +78,15 @@ gtkdemo_deps = [ libgtk_dep, ]
 
 extra_demo_sources = files(['main.c', 'gtkfishbowl.c', 'fontplane.c', 'gtkgears.c', 'puzzlepiece.c'])
 
-if harfbuzz_dep.found() and pangoft_dep.found()
+if build_with_harfbuzz
   demos += files('font_features.c')
-  extra_demo_sources += files(['script-names.c', 'language-names.c'])
+  if pangoft_dep.found()
+    extra_demo_sources += files(['script-names.c', 'language-names.c'])
+  endif
   gtkdemo_deps += [ harfbuzz_dep, ]
+  if add_freetype_lib
+    gtkdemo_deps += [ ft2_dep, ]
+  endif
 endif
 
 if os_unix
@@ -104,7 +109,7 @@ executable('gtk4-demo',
            c_args: gtkdemo_args,
            dependencies: gtkdemo_deps,
            include_directories: confinc,
-           gui_app: true,
+#           gui_app: true,
            link_args: extra_demo_ldflags,
            install: true)
 
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index 4a7182758f..235658a4bc 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -38,6 +38,19 @@
 
 #include <dwmapi.h>
 
+#ifdef HAVE_HARFBUZZ
+# include <initguid.h>
+# include <pango/pangowin32.h>
+extern GType _pango_win32_font_get_type (void) G_GNUC_CONST;
+
+# define PANGO_TYPE_WIN32_FONT            (_pango_win32_font_get_type ())
+# define PANGO_WIN32_FONT(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT, 
PangoWin32Font))
+# define PANGO_WIN32_FONT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+# define PANGO_WIN32_IS_FONT(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT))
+# define PANGO_WIN32_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT))
+# define PANGO_WIN32_FONT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+#endif
+
 static int debug_indent = 0;
 
 /**
@@ -691,6 +704,20 @@ gdk_win32_display_dispose (GObject *object)
         }
     }
 
+#ifdef HAVE_HARFBUZZ
+  g_hash_table_destroy (display_win32->ht_pango_dwrite_fonts);
+  g_hash_table_destroy (display_win32->ht_pango_logfonts);
+  g_hash_table_destroy (display_win32->ht_pango_win32_ft_faces);
+  g_hash_table_destroy (display_win32->ht_pango_win32_ft_data);
+  if (display_win32->ft_lib != NULL)
+    FT_Done_FreeType (display_win32->ft_lib);
+
+  if (display_win32->dwrite_gdi_interop != NULL)
+    IDWriteGdiInterop_Release (display_win32->dwrite_gdi_interop);
+
+  if (display_win32->dwrite_factory != NULL)
+    IDWriteFactory_Release (display_win32->dwrite_factory);
+#endif
   G_OBJECT_CLASS (gdk_win32_display_parent_class)->dispose (object);
 }
 
@@ -902,6 +929,20 @@ _gdk_win32_enable_hidpi (GdkWin32Display *display)
     }
 }
 
+#ifdef HAVE_HARFBUZZ
+/*
+ * We need to release the IDWriteFonts using IDWriteFont_Release(),
+ * but since it is a macro that depends on what we feed to it, we
+ * need a small C-function that calls that for us, so that we can pass
+ * it to g_hash_table_new_full()
+ */
+static void
+gdk_win32_release_dwrite_font (IDWriteFont *dwrite_font)
+{
+  IDWriteFont_Release (dwrite_font);
+}
+#endif
+
 static void
 gdk_win32_display_init (GdkWin32Display *display)
 {
@@ -925,6 +966,12 @@ gdk_win32_display_init (GdkWin32Display *display)
   else
     display->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display, NULL, NULL, NULL);
 
+#ifdef HAVE_HARFBUZZ
+  display->ht_pango_dwrite_fonts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, 
gdk_win32_release_dwrite_font);
+  display->ht_pango_logfonts = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+  display->ht_pango_win32_ft_faces = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, 
FT_Done_Face);
+  display->ht_pango_win32_ft_data = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+#endif
   _gdk_win32_display_init_cursors (display);
   gdk_win32_display_check_composited (display);
 }
@@ -1085,6 +1132,470 @@ gdk_win32_display_get_last_seen_time (GdkDisplay *display)
   return GetMessageTime ();
 }
 
+#ifdef HAVE_HARFBUZZ
+static IDWriteGdiInterop *
+gdk_win32_display_get_dwrite_gdi_interop (GdkWin32Display *display)
+{
+  HRESULT hr = S_OK;
+
+  if (display->dwrite_factory == NULL)
+    hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED,
+                              &IID_IDWriteFactory,
+                              (IUnknown **) &display->dwrite_factory);
+
+  if (SUCCEEDED (hr) && display->dwrite_gdi_interop == NULL)
+    hr = IDWriteFactory_GetGdiInterop (display->dwrite_factory,
+                                       &display->dwrite_gdi_interop);
+
+  if (FAILED (hr))
+    {
+      g_critical ("Failed to initialize DirectWrite, font tweaking will likely not work!");
+      display->dwrite_factory = NULL;
+      display->dwrite_gdi_interop = NULL;
+    }
+
+  return display->dwrite_gdi_interop;
+}
+
+static FT_Library
+gdk_win32_display_get_ft_lib (GdkWin32Display *display)
+{
+  FT_Error ft_err = FT_Err_Ok;
+
+  if (display->ft_lib == NULL)
+    ft_err = FT_Init_FreeType (&display->ft_lib);
+
+  if (ft_err != FT_Err_Ok)
+    {
+      g_critical ("Failed to initialize FreeType, font tweaking will likely not work!");
+      display->ft_lib = NULL;
+    }
+
+  return (display->ft_lib);
+}
+
+IDWriteFont *
+gdk_win32_get_dwrite_font_from_pango_font (GdkDisplay *display,
+                                           PangoFont  *pango_font)
+{
+  IDWriteFont *dwrite_font = NULL;
+  GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
+
+  dwrite_font = g_hash_table_lookup (display_win32->ht_pango_dwrite_fonts,
+                                     pango_font);
+
+  /* If we are using PangoWin32, we need to turn the LOGFONTW to a IDWriteFont */
+  if (dwrite_font == NULL && PANGO_WIN32_IS_FONT (pango_font))
+    {
+      /* first acquire the LOGFONTW from the pango_font that we are using, so that we can feed it into 
DirectWrite */
+      LOGFONTW *logfont = pango_win32_font_logfontw (pango_font);
+         HRESULT hr = S_OK;
+      gboolean succeeded = TRUE;
+
+      IDWriteGdiInterop *dwrite_gdi_interop = NULL;
+
+      dwrite_gdi_interop = gdk_win32_display_get_dwrite_gdi_interop (display_win32);
+
+      if (dwrite_gdi_interop == NULL)
+        {
+          g_critical ("Failed to initialize DirectWrite.  Font tweaking will likely not work!");
+          succeeded = FALSE;
+        }
+
+      if (FAILED (IDWriteGdiInterop_CreateFontFromLOGFONT (dwrite_gdi_interop,
+                                                           logfont,
+                                                           &dwrite_font)))
+        {
+          g_warning ("Could not acquire DirectWrite Font from LOGFONTW!");
+          succeeded = FALSE;
+        }
+
+      /* cache up the LOGFONTW/IDWriteFont */
+      if (!g_hash_table_insert (display_win32->ht_pango_logfonts, pango_font, logfont))
+        g_warning ("Could not cache LOGFONTW!");
+      if (!g_hash_table_insert (display_win32->ht_pango_dwrite_fonts, pango_font, dwrite_font))
+        g_warning ("Could not cache DirectWrite Font!");
+
+      if (!succeeded)
+        dwrite_font = NULL;
+    }
+
+  return dwrite_font;
+}
+
+FT_Face
+gdk_win32_get_ft_face_from_pango_font (GdkDisplay *display,
+                                       PangoFont  *pango_font)
+{
+  GdkWin32Display *display_win32 = GDK_WIN32_DISPLAY (display);
+  FT_Face ft_face = NULL;
+
+  ft_face = g_hash_table_lookup (display_win32->ht_pango_win32_ft_faces, pango_font);
+
+  if (ft_face == NULL && PANGO_WIN32_IS_FONT (pango_font))
+    {
+         HRESULT hr = S_OK;
+
+      IDWriteFont *dwrite_font = NULL;
+      IDWriteFontFace *dwrite_font_face = NULL;
+      IDWriteFontFile *dwrite_font_file = NULL;
+      IDWriteFontFileLoader *dwrite_font_file_loader = NULL;
+      IDWriteFontFileStream *dwrite_font_file_stream = NULL;
+      IDWriteLocalizedStrings *lstrings = NULL;
+
+      /*
+      IDWriteTextFormat *text_format = NULL;
+      IDWriteFontFamily *family = NULL;
+      DWRITE_FONT_WEIGHT font_weight;
+      DWRITE_FONT_STYLE font_style;
+      DWRITE_FONT_STRETCH font_stretch; */
+      void *dwrite_ref_key;
+      FT_Library ft_lib;
+      FT_Byte *font_file_data = NULL;
+      FT_Error ft_err;
+
+      BOOL property_found = FALSE;
+      UINT32 count, i, size, dwrite_ref_key_size;
+      UINT64 font_file_size;
+      const void *font_fragment_start;
+      void *font_fragment_ctx;
+      gboolean succeeded = TRUE;
+      gboolean release_fragment_ctx = FALSE;
+         gchar *font_name = NULL;
+      wchar_t *wstr = NULL;
+
+      /*
+      wchar_t *family_name = NULL;
+      wchar_t locale[LOCALE_NAME_MAX_LENGTH];
+      wchar_t *font_file_path = NULL;
+      gchar *str = NULL;
+      UINT32 nlangs = 0;*/
+
+      ft_lib = gdk_win32_display_get_ft_lib (display_win32);
+
+      if (ft_lib == NULL)
+        {
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      dwrite_font = gdk_win32_get_dwrite_font_from_pango_font (display, pango_font);
+
+      if (dwrite_font == NULL)
+        {
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+      /*
+      font_weight = IDWriteFont_GetWeight (dwrite_font);
+      font_style = IDWriteFont_GetStyle (dwrite_font);
+      font_stretch = IDWriteFont_GetStretch (dwrite_font); */
+
+      hr = IDWriteFont_GetInformationalStrings (dwrite_font,
+                                                DWRITE_INFORMATIONAL_STRING_FULL_NAME,
+                                                &lstrings,
+                                                &property_found);
+
+      if (SUCCEEDED (hr) && property_found)
+        {
+          if (SUCCEEDED (IDWriteLocalizedStrings_GetStringLength (lstrings, 0, &size)))
+            {
+              wstr = g_new0 (wchar_t, size + 1);
+              IDWriteLocalizedStrings_GetString (lstrings, 0, wstr, size + 1);
+              font_name = g_utf16_to_utf8 (wstr, -1, NULL, NULL, NULL);
+              g_free (wstr);
+              IDWriteLocalizedStrings_Release (lstrings);
+            }
+        }
+
+      if (SUCCEEDED (hr) && !property_found)
+        g_print ("Could not find full name of DirectWriteFont %p!\n", dwrite_font);
+
+      if (FAILED (IDWriteFont_CreateFontFace (dwrite_font,
+                                              &dwrite_font_face)))
+        {
+          g_warning ("Could not create Font Face for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFace_GetFiles (dwrite_font_face, &size, NULL)) ||
+          FAILED (IDWriteFontFace_GetFiles (dwrite_font_face, &size, &dwrite_font_file)))
+        {
+          g_warning ("Could not obtain files from Font Face for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFile_GetReferenceKey (dwrite_font_file,
+                                                   &dwrite_ref_key,
+                                                   &dwrite_ref_key_size)))
+        {
+          g_warning ("Could not obtain reference key from Font Face for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFile_GetLoader (dwrite_font_file, &dwrite_font_file_loader)))
+        {
+          g_warning ("Could not obtain loader from Font Face for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFileLoader_CreateStreamFromKey (dwrite_font_file_loader,
+                                                             dwrite_ref_key,
+                                                             dwrite_ref_key_size,
+                                                             &dwrite_font_file_stream)))
+        {
+          g_warning ("Could not obtain Font Face file stream for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFileStream_GetFileSize (dwrite_font_file_stream, &font_file_size)))
+        {
+          g_warning ("Could not acquire font file size for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+      if (FAILED (IDWriteFontFileStream_ReadFileFragment (dwrite_font_file_stream,
+                                                          &font_fragment_start,
+                                                          0,
+                                                          font_file_size,
+                                                          &font_fragment_ctx)))
+        {
+          g_warning ("Could not acquire raw font data for font for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+      else
+        release_fragment_ctx = TRUE;
+
+      font_file_data = g_new0 (FT_Byte, font_file_size);
+      memcpy (font_file_data, font_fragment_start, (size_t) font_file_size);
+      ft_err = FT_New_Memory_Face (ft_lib, font_file_data, font_file_size, 0, &ft_face);
+
+      if (ft_err != FT_Err_Ok)
+        {
+          g_warning ("Unable to obtain FreeType Face for font %s", font_name);
+          succeeded = FALSE;
+          goto dwrite_fail;
+        }
+
+dwrite_fail:
+      if (release_fragment_ctx)
+        IDWriteFontFileStream_ReleaseFileFragment (dwrite_font_file_stream, &font_fragment_ctx);
+      if (dwrite_font_file_stream != NULL)
+        IDWriteFontFileStream_Release (dwrite_font_file_stream);
+      if (dwrite_font_file_loader != NULL)
+        IDWriteFontFileLoader_Release (dwrite_font_file_loader);
+      if (dwrite_font_file != NULL)
+        IDWriteFontFile_Release (dwrite_font_file);
+      if (dwrite_font_face != NULL)
+        IDWriteFontFace_Release (dwrite_font_face);
+
+      if (font_name != NULL)
+        g_free (font_name);
+
+      if (succeeded)
+        {
+          g_hash_table_insert (display_win32->ht_pango_win32_ft_data, pango_font, font_file_data);
+          g_hash_table_insert (display_win32->ht_pango_win32_ft_faces, pango_font, ft_face);
+        }
+      else
+        ft_face = NULL;
+#if 0
+      /* Use FreeType & HarfBuzz for now */
+      hr = IDWriteFont_GetInformationalStrings (dwrite_font,
+                                                DWRITE_INFORMATIONAL_STRING_FULL_NAME,
+                                                &lstrings,
+                                                &property_found);
+
+      if (SUCCEEDED (hr) && property_found)
+        {
+          count = IDWriteLocalizedStrings_GetCount (lstrings);
+          g_print ("DWRITE_INFORMATIONAL_STRING_FULL_NAME strings: %d\n", count);
+
+          for (i = 0; i < count; i++)
+            {
+              hr = IDWriteLocalizedStrings_GetStringLength (lstrings, i, &size);
+              if (SUCCEEDED (hr))
+                {
+                  wstr = g_new0 (wchar_t, size + 1);
+                  hr = IDWriteLocalizedStrings_GetString (lstrings, i, wstr, size + 1);
+                  str = g_utf16_to_utf8 (wstr, -1, NULL, NULL, NULL);
+                  g_print ("index[%d]: %s\n", i, str);
+                  g_free (str);
+                  g_free (wstr);
+                }
+              else
+                break;
+            }
+        }
+
+      if (SUCCEEDED (hr) && !property_found)
+        g_print ("Could not find full name of font!\n");
+
+      if (FAILED (hr))
+        {
+          g_warning ("Failed to acquire full name of font!\n");
+          return;
+        }
+
+      if (SUCCEEDED (hr) && property_found)
+        IDWriteLocalizedStrings_Release (lstrings);
+
+      /* Get the family of the font to get the locales/languages that it supports */
+      if (SUCCEEDED (hr))
+        hr = IDWriteFont_GetFontFamily (dwrite_font, &family);
+
+      if (SUCCEEDED (hr))
+        hr = IDWriteFontFamily_GetFamilyNames (family, &lstrings);
+
+      if (SUCCEEDED (hr))
+        nlangs = IDWriteLocalizedStrings_GetCount (lstrings);
+
+      IDWriteLocalizedStrings_GetLocaleName (lstrings, 0, locale, LOCALE_NAME_MAX_LENGTH);
+      wstr = g_new0 (wchar_t, LOCALE_NAME_MAX_LENGTH);
+
+      for (i = 0; i < nlangs; i++)
+        {
+          IDWriteLocalizedStrings_GetLocaleName (lstrings, i, wstr, LOCALE_NAME_MAX_LENGTH);
+
+          if (SUCCEEDED (hr))
+            {
+               wchar_t *disp_strw = NULL;
+               LCTYPE disp_type = g_win32_check_windows_version (6, 1, 0, G_WIN32_OS_ANY) ?
+                                  LOCALE_SLOCALIZEDDISPLAYNAME :
+                                  LOCALE_SLOCALIZEDLANGUAGENAME;
+               size = GetLocaleInfoEx (wstr, disp_type, disp_strw, 0);
+               if (size != 0)
+                 disp_strw = g_new0 (wchar_t, size);
+               if ((size != 0 && GetLocaleInfoEx (wstr, disp_type, disp_strw, size)) != 0)
+                 {
+                   gchar *localestr = g_utf16_to_utf8 (wstr, -1, NULL, NULL, NULL);
+                   gchar *disp_str = g_utf16_to_utf8 (disp_strw, size - 1, NULL, NULL, NULL);
+                   g_print ("locale %d: %s\n", i, localestr);
+                   g_free (disp_strw);
+                   g_free (localestr);
+                   g_free (disp_str);
+                 }
+               else
+                 {
+                   g_print ("Uh-oh, we could not acquire the localized locale name, %d\n", GetLastError ());
+                   return;
+                 }
+             }
+           else
+             {
+                g_warning ("Unable to acquire font locale with DirectWrite\n");
+                return;
+             }
+         }
+      g_free (wstr);
+
+      if (SUCCEEDED (hr))
+        hr = IDWriteFont_GetInformationalStrings (dwrite_font,
+                                                  DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES,
+                                                  &lstrings,
+                                                  &property_found);
+
+      if (SUCCEEDED (hr))
+        {
+          if (property_found)
+            {
+              count = IDWriteLocalizedStrings_GetCount (lstrings);
+              g_print ("DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES strings: %d\n", count);
+
+              hr = IDWriteLocalizedStrings_GetStringLength (lstrings, 0, &size);
+              if (SUCCEEDED (hr))
+                {
+                  family_name = g_new0 (wchar_t, size + 1);
+                  hr = IDWriteLocalizedStrings_GetString (lstrings, 0, family_name, size + 1);
+                  str = g_utf16_to_utf8 (family_name, -1, NULL, NULL, NULL);
+                  g_print ("Win32 Family Name: %s\n", str);
+                  g_free (str);
+                  IDWriteLocalizedStrings_Release (lstrings);
+                }
+            }
+          else
+            g_print ("Could not find language/script tag of font!\n");
+        }
+
+         if (FAILED (hr))
+        {
+          g_warning ("Failed to acquire the supported script/language tags!\n");
+          if (family_name != NULL)
+            g_free (family_name);
+          return;
+        }
+
+      if (SUCCEEDED (hr))
+        hr = IDWriteFont_GetInformationalStrings (dwrite_font,
+                                                  DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG,
+                                                  &lstrings,
+                                                  &property_found);
+
+      if (SUCCEEDED (hr))
+        {
+          if (property_found)
+            {
+              count = IDWriteLocalizedStrings_GetCount (lstrings);
+              g_print ("DWRITE_INFORMATIONAL_STRING_SUPPORTED_SCRIPT_LANGUAGE_TAG strings: %d\n", count);
+              for (i = 0; i < count; i++)
+                {
+                  hr = IDWriteLocalizedStrings_GetStringLength (lstrings, i, &size);
+                  if (SUCCEEDED (hr))
+                    {
+                      gchar * localestr = NULL;
+
+                      wstr = g_new0 (wchar_t, size + 1);
+                      hr = IDWriteLocalizedStrings_GetString (lstrings, i, wstr, size + 1);
+                      str = g_utf16_to_utf8 (wstr, -1, NULL, NULL, NULL);
+                      g_print ("index[%d]: %s\n", i, str);
+                      g_free (str);
+                      g_free (wstr);
+                    }
+                  else
+                    break;
+                }
+
+              IDWriteLocalizedStrings_Release (lstrings);
+            }
+          else
+            g_print ("Could not find language/script tag of font!\n");
+        }
+      else
+        {
+          g_warning ("Failed to acquire the supported script/language tags!\n");
+          return;
+        }
+
+      hr = IDWriteFactory_CreateTextFormat (priv->dwrite_factory,
+                                            family_name,
+                                            NULL,
+                                            font_weight,
+                                            font_style,
+                                            font_stretch,
+                                            72.0f,
+                                            locale,
+                                            &text_format);
+
+      g_print ("Text format: %s\n", SUCCEEDED (hr) ? "yes" : "no");
+      if (family_name != NULL)
+        g_free (family_name);
+
+      IDWriteTextFormat_Release (text_format);
+      IDWriteFontFamily_Release (family);
+#endif /* if 0 */
+    }
+
+  return ft_face;
+}
+#endif
+
 static void
 gdk_win32_display_class_init (GdkWin32DisplayClass *klass)
 {
diff --git a/gdk/win32/gdkdisplay-win32.h b/gdk/win32/gdkdisplay-win32.h
index a4d9cc7378..f3b4705782 100644
--- a/gdk/win32/gdkdisplay-win32.h
+++ b/gdk/win32/gdkdisplay-win32.h
@@ -25,6 +25,12 @@
 #include "gdkwin32screen.h"
 #include "gdkwin32cursor.h"
 
+#ifdef HAVE_HARFBUZZ
+# define COBJMACROS
+# include <hb-ft.h>
+# include "dwrite_c.h"
+#endif
+
 /* Define values used to set DPI-awareness */
 typedef enum _GdkWin32ProcessDpiAwareness {
   PROCESS_DPI_UNAWARE = 0,
@@ -113,6 +119,16 @@ struct _GdkWin32Display
 
   /* Message filters */
   GList *filters;
+
+#ifdef HAVE_HARFBUZZ
+  IDWriteFactory *dwrite_factory;
+  IDWriteGdiInterop *dwrite_gdi_interop;
+  FT_Library ft_lib;
+  GHashTable *ht_pango_dwrite_fonts;
+  GHashTable *ht_pango_logfonts;
+  GHashTable *ht_pango_win32_ft_data;
+  GHashTable *ht_pango_win32_ft_faces;
+#endif
 };
 
 struct _GdkWin32DisplayClass
diff --git a/gdk/win32/gdkwin32misc.h b/gdk/win32/gdkwin32misc.h
index e8133f0748..5327e29698 100644
--- a/gdk/win32/gdkwin32misc.h
+++ b/gdk/win32/gdkwin32misc.h
@@ -99,6 +99,24 @@ void          gdk_win32_set_modal_dialog_libgtk_only (HWND window);
 
 #endif
 
+#if defined (HAVE_HARFBUZZ) && \
+    (defined (INSIDE_GDK_WIN32) || defined (GDK_COMPILATION) || \
+     defined (GTK_COMPILATION) || defined (GTK_DEMO_FONT_FEATURES))
+
+/* For internal GTK use only */
+#define COBJMACROS
+#include "dwrite_c.h"
+#include <hb-ft.h>
+
+GDK_AVAILABLE_IN_ALL
+IDWriteFont *gdk_win32_get_dwrite_font_from_pango_font (GdkDisplay *display,
+                                                        PangoFont  *pango_font);
+
+GDK_AVAILABLE_IN_ALL
+FT_Face gdk_win32_get_ft_face_from_pango_font (GdkDisplay *display,
+                                               PangoFont  *pango_font);
+
+#endif
 G_END_DECLS
 
 #endif /* __GDK_WIN32_MISC_H__ */
diff --git a/gtk/gtkfontchooserwidget.c b/gtk/gtkfontchooserwidget.c
index afe1b922fb..95f28ca331 100644
--- a/gtk/gtkfontchooserwidget.c
+++ b/gtk/gtkfontchooserwidget.c
@@ -56,16 +56,42 @@
 #include "gtkgesturemultipress.h"
 #include "gtkeventcontrollerscroll.h"
 
-#if defined(HAVE_HARFBUZZ) && defined(HAVE_PANGOFT)
-#include <pango/pangofc-font.h>
-#include <hb.h>
-#include <hb-ot.h>
-#include <hb-ft.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_MULTIPLE_MASTERS_H
-#include "language-names.h"
-#include "script-names.h"
+#if defined(HAVE_HARFBUZZ)
+# if defined GDK_WINDOWING_WIN32
+#  define _WIN32_WINNT 0x0600
+#  define WIN32_LEAN_AND_MEAN
+#  define COBJMACROS
+#  include <windows.h>
+#  include <initguid.h>
+#  include "gdk/win32/dwrite_c.h"
+#  include "gdk/win32/gdkwin32.h"
+
+#  include <pango/pangowin32.h>
+extern GType _pango_win32_font_get_type (void) G_GNUC_CONST;
+
+#  define PANGO_TYPE_WIN32_FONT            (_pango_win32_font_get_type ())
+#  define PANGO_WIN32_FONT(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_WIN32_FONT, 
PangoWin32Font))
+#  define PANGO_WIN32_FONT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+#  define PANGO_WIN32_IS_FONT(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_WIN32_FONT))
+#  define PANGO_WIN32_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_WIN32_FONT))
+#  define PANGO_WIN32_FONT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_WIN32_FONT, 
PangoWin32FontClass))
+# endif
+# if defined(HAVE_PANGOFT)
+#  include <pango/pangofc-font.h>
+# endif
+
+# include <hb.h>
+# include <hb-ot.h>
+# include <hb-ft.h>
+# include <ft2build.h>
+# include FT_FREETYPE_H
+# include FT_MULTIPLE_MASTERS_H
+
+# ifdef HAVE_PANGOFT
+#  include "language-names.h"
+#  include "script-names.h"
+# endif
+
 #endif
 
 #include "open-type-layout.h"
@@ -820,6 +846,78 @@ axis_free (gpointer v)
   g_free (a);
 }
 
+#ifdef GDK_WINDOWING_WIN32
+
+/* if we are using native Windows (PangoWin32), use DirectWrite */
+static BOOL CALLBACK
+get_win32_all_locales_scripts (LPWSTR locale_w, DWORD flags, LPARAM param)
+{
+  wchar_t *langname_w = NULL;
+  wchar_t *locale_abbrev_w = NULL;
+  gchar *langname, *locale_abbrev, *locale, *p;
+  gint i;
+  hb_language_t lang;
+  GHashTable *ht_scripts_langs = (GHashTable *)param;
+
+  gint langname_size, locale_abbrev_size;
+  langname_size = GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, 0);
+  if (langname_size == 0)
+    return FALSE;
+
+  langname_w = g_new0 (wchar_t, langname_size);
+
+  if (langname_size == 0)
+    return FALSE;
+
+  GetLocaleInfoEx (locale_w, LOCALE_SLOCALIZEDDISPLAYNAME, langname_w, langname_size);
+  langname = g_utf16_to_utf8 (langname_w, -1, NULL, NULL, NULL);
+  locale = g_utf16_to_utf8 (locale_w, -1, NULL, NULL, NULL);
+  p = strchr (locale, '-');
+  lang = hb_language_from_string (locale, p ? p - locale : -1);
+  if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
+    g_hash_table_insert (ht_scripts_langs, lang, langname);
+
+  /* track 3-letter ISO639-2/3 language codes as well */
+  locale_abbrev_size = GetLocaleInfoEx (locale_w, LOCALE_SABBREVLANGNAME, locale_abbrev_w, 0);
+  if (locale_abbrev_size > 0)
+    {
+      locale_abbrev_w = g_new0 (wchar_t, locale_abbrev_size);
+      GetLocaleInfoEx (locale_w, LOCALE_SABBREVLANGNAME, locale_abbrev_w, locale_abbrev_size);
+
+         locale_abbrev = g_utf16_to_utf8 (locale_abbrev_w, -1, NULL, NULL, NULL);
+      lang = hb_language_from_string (locale_abbrev, -1);
+      if (g_hash_table_lookup (ht_scripts_langs, lang) == NULL)
+        g_hash_table_insert (ht_scripts_langs, lang, langname);
+
+      g_free (locale_abbrev);
+      g_free (locale_abbrev_w);
+    }
+
+  g_free (locale);
+  g_free (langname_w);
+
+  return TRUE;
+}
+
+_GDK_EXTERN GHashTable *
+gtk_font_chooser_widget_get_win32_locales (void)
+{
+  static GHashTable *ht_langtag_locales = NULL;
+  static volatile gsize inited = 0;
+
+  if (g_once_init_enter (&inited))
+    {
+      gchar *locales, *script;
+      ht_langtag_locales = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+      EnumSystemLocalesEx (&get_win32_all_locales_scripts, LOCALE_ALL, (LPARAM)ht_langtag_locales, NULL);
+      g_once_init_leave (&inited, 1);
+    }
+
+  return ht_langtag_locales;
+}
+
+#endif /* GDK_WINDOWING_WIN32 */
+
 static void
 gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser)
 {
@@ -870,7 +968,7 @@ gtk_font_chooser_widget_init (GtkFontChooserWidget *fontchooser)
   /* Load data and set initial style-dependent parameters */
   gtk_font_chooser_widget_load_fonts (fontchooser, TRUE);
 
-#if defined(HAVE_HARFBUZZ) && defined(HAVE_PANGOFT)
+#if defined(HAVE_HARFBUZZ)
   gtk_font_chooser_widget_populate_features (fontchooser);
 #endif
 
@@ -1459,7 +1557,7 @@ gtk_font_chooser_widget_ensure_selection (GtkFontChooserWidget *fontchooser)
     }
 }
 
-#if defined(HAVE_HARFBUZZ) && defined(HAVE_PANGOFT)
+#if defined(HAVE_HARFBUZZ)
 
 /* OpenType variations */
 
@@ -1610,9 +1708,11 @@ gtk_font_chooser_widget_update_font_variations (GtkFontChooserWidget *fontchoose
 {
   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
   PangoFont *pango_font;
+ 
   FT_Face ft_face;
   FT_MM_Var *ft_mm_var;
   FT_Error ret;
+  FT_Byte *font_file_data = NULL;
   gboolean has_axis = FALSE;
 
   if (priv->updating_variations)
@@ -1626,7 +1726,16 @@ gtk_font_chooser_widget_update_font_variations (GtkFontChooserWidget *fontchoose
 
   pango_font = pango_context_load_font (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)),
                                         priv->font_desc);
-  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (PANGO_WIN32_IS_FONT (pango_font))
+    ft_face = gdk_win32_get_ft_face_from_pango_font (gtk_widget_get_display (GTK_WIDGET (fontchooser)),
+                                                     pango_font);
+#endif
 
   ret = FT_Get_MM_Var (ft_face, &ft_mm_var);
   if (ret == 0)
@@ -1658,7 +1767,11 @@ gtk_font_chooser_widget_update_font_variations (GtkFontChooserWidget *fontchoose
       free (ft_mm_var);
     }
 
-  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#endif
+
   g_object_unref (pango_font);
 
   return has_axis;
@@ -2126,6 +2239,8 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
   GtkFontChooserWidgetPrivate *priv = fontchooser->priv;
   PangoFont *pango_font;
   FT_Face ft_face;
+  FT_Byte *font_file_data = NULL;
+
   hb_font_t *hb_font;
   hb_tag_t script_tag;
   hb_tag_t lang_tag;
@@ -2147,7 +2262,17 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
 
   pango_font = pango_context_load_font (gtk_widget_get_pango_context (GTK_WIDGET (fontchooser)),
                                         priv->font_desc);
-  ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font)),
+
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    ft_face = pango_fc_font_lock_face (PANGO_FC_FONT (pango_font));
+#endif
+#ifdef GDK_WINDOWING_WIN32
+  if (PANGO_WIN32_IS_FONT (pango_font))
+    ft_face = gdk_win32_get_ft_face_from_pango_font (gtk_widget_get_display (GTK_WIDGET (fontchooser)),
+                                                     pango_font);
+#endif
+
   hb_font = hb_ft_font_create (ft_face, NULL);
 
   if (hb_font)
@@ -2207,7 +2332,11 @@ gtk_font_chooser_widget_update_font_features (GtkFontChooserWidget *fontchooser)
       hb_font_destroy (hb_font);
     }
 
-  pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#ifdef HAVE_PANGOFT
+  if (PANGO_IS_FC_FONT (pango_font))
+    pango_fc_font_unlock_face (PANGO_FC_FONT (pango_font));
+#endif
+
   g_object_unref (pango_font);
 
   return has_feature;
@@ -2307,7 +2436,7 @@ gtk_font_chooser_widget_merge_font_desc (GtkFontChooserWidget       *fontchooser
 
       gtk_font_chooser_widget_update_marks (fontchooser);
 
-#if defined(HAVE_HARFBUZZ) && defined(HAVE_PANGOFT)
+#if defined(HAVE_HARFBUZZ)
       if (gtk_font_chooser_widget_update_font_features (fontchooser))
         has_tweak = TRUE;
       if (gtk_font_chooser_widget_update_font_variations (fontchooser))
diff --git a/gtk/meson.build b/gtk/meson.build
index 8559ed0f7c..9b8c1fa94e 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -882,12 +882,17 @@ gtk_deps = [
   graphene_dep,
 ]
 
-if harfbuzz_dep.found() and pangoft_dep.found()
-  gtk_deps += [ harfbuzz_dep, pangoft_dep ]
-  gtk_sources += files([
-  'language-names.c',
-  'script-names.c',
-  ])
+if build_with_harfbuzz
+  gtk_deps += [ harfbuzz_dep ]
+  if pangoft_dep.found()
+    gtk_deps += [ pangoft_dep ]
+    gtk_sources += files([
+    'language-names.c',
+    'script-names.c',
+    ])
+  elif add_freetype_lib
+    gtk_deps += [ ft2_dep ]
+  endif
 endif
 
 if x11_enabled
@@ -908,7 +913,7 @@ endif
 
 if win32_enabled
   gtk_cargs += ['-DGTK_PRINT_BACKENDS="file,lpr"']
-  gtk_deps += [ giowin32_dep, pangowin32_dep ]
+  gtk_deps += [ giowin32_dep, pangowin32_dep, dwrite_dep ]
 
   gtk_deps += [cc.find_library('advapi32'),
                cc.find_library('comctl32'),
diff --git a/meson.build b/meson.build
index 53504f9279..9896683aed 100644
--- a/meson.build
+++ b/meson.build
@@ -313,6 +313,7 @@ gobject_dep    = dependency('gobject-2.0', version: glib_req,
 if os_win32
   giowin32_dep = dependency('gio-windows-2.0', version: glib_req, required: win32_enabled,
                             fallback : ['glib', 'libgio_dep'])
+  dwrite_dep = cc.find_library('dwrite', required : true)
 endif
 if os_unix
   giounix_dep  = dependency('gio-unix-2.0', version: glib_req, required: false,
@@ -330,7 +331,9 @@ require_pangoft2 = wayland_enabled or x11_enabled
 pangoft_dep    = dependency('pangoft2', required: require_pangoft2,
                             fallback : ['pango', 'libpangoft2_dep'])
 
-if pangoft_dep.found()
+ft2_dep = []
+
+if pangoft_dep.found() or os_win32
   # Need at least 2.7.1 for FT_Get_Var_Design_Coordinates()
   # We get the dependency itself from pango, but pango doesn't care
   # about ft2 version, so an extra check is needed.
@@ -422,6 +425,9 @@ if cairogobj_dep.found()
 endif
 
 cairo_libs = []
+
+add_freetype_lib = false
+
 if cc.get_id() == 'msvc'
   # Fallback depedency discovery for those on Visual Studio that do not generate
   # pkg-config files in their build systems for MSVC
@@ -449,11 +455,22 @@ if cc.get_id() == 'msvc'
   if not harfbuzz_dep.found()
     if cc.has_header('hb.h')
       harfbuzz_dep = cc.find_library('harfbuzz', required : false)
+      if harfbuzz_dep.found()
+        add_freetype_lib = true
+      endif
     endif
   endif
 endif
 
-cdata.set('HAVE_HARFBUZZ', harfbuzz_dep.found())
+build_with_harfbuzz = false
+
+if pangoft_dep.found()
+  build_with_harfbuzz = true
+elif os_win32 and harfbuzz_dep.found() and ft2_dep.found()
+  build_with_harfbuzz = cc.has_header_symbol('hb-ft.h', 'hb_ft_face_create', dependencies : harfbuzz_dep)
+endif
+
+cdata.set('HAVE_HARFBUZZ', build_with_harfbuzz)
 cdata.set('HAVE_PANGOFT', pangoft_dep.found())
 
 atk_pkgs = ['atk']



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]