[gtk/wip/fanc999/fontchooser.win32.gtk3: 1/3] gtk/: Add a utility source to obtain a FT_Face from a PangoFont



commit e849755883f9c80bcfaf3b6c97c507894b500c26
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Fri Jan 4 18:23:26 2019 +0800

    gtk/: Add a utility source to obtain a FT_Face from a PangoFont
    
    ...Which is necessary on Windows when PangoFT2 is not being used.  This
    is a source file that is included by both gtk/gtkfontchooserwidget.c and
    demos/gtk-demo/font_features.c.  Define macros in there so that the code
    will pick the right code path depending on:
    
    -Whether we are running on Windows.
    -If we are on Windows, determine whether we are using PangoFT2 or
     PangoWin32, if PangoFT2 support is enabled.
    -If PangoFT2 is being used, acquire the FT_Face as we did before.
    -Otherwise (on Windows), obtain the FT_Face by using the HFONT that we
     obtain from PangoWin32.

 gtk/Makefile.am                 |   3 +-
 gtk/gtk-pangofont-ftface-util.c | 228 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 230 insertions(+), 1 deletion(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 8e86bce763..453aa42ad7 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -1171,7 +1171,8 @@ gtk_extra_sources =                               \
        deprecated/gtkstatusicon-quartz.c       \
        gtkversion.h.in                         \
        gtkmarshalers.list                      \
-       fallback-c89.c
+       fallback-c89.c                          \
+       gtk-pangofont-ftface-util.c
 
 #
 # setup GTK+ sources and their dependencies
diff --git a/gtk/gtk-pangofont-ftface-util.c b/gtk/gtk-pangofont-ftface-util.c
new file mode 100644
index 0000000000..2a2379f2e7
--- /dev/null
+++ b/gtk/gtk-pangofont-ftface-util.c
@@ -0,0 +1,228 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Chun-wei Fan <fanc999 yahoo com tw>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_PANGOFT
+# include <pango/pangofc-font.h>
+
+/* On Windows, we need to check whether the PangoFont is a FontConfig Font or a Win32/GDI font,
+ * and acquire/release the FT_Face accordingly.
+ */
+# ifdef GDK_WINDOWING_WIN32
+#  define FT_EXT_ITEM_INIT(f)   \
+          PANGO_IS_FC_FONT(f) ? \
+          NULL : \
+          g_new0 (gtk_win32_ft_items, 1)
+
+#  define FT_FACE_FROM_PANGO_FONT(i,f,m) \
+          PANGO_IS_FC_FONT(f) ?          \
+          pango_fc_font_lock_face (PANGO_FC_FONT (f)) : \
+          pangowin32_font_get_ftface (i, f, m)
+
+#  define PANGO_FONT_RELEASE_FT_FACE(i,f) \
+          PANGO_IS_FC_FONT(f) ?           \
+          pango_fc_font_unlock_face (PANGO_FC_FONT (f)) : \
+          pangowin32_font_get_ftface_release_ftface (i);
+
+#  define RELEASE_EXTRA_FT_ITEMS(i) release_extra_ft_items(i)
+
+# else /* On non-Windows, acquire/release the FT_Face as we did before */
+#  define FT_EXT_ITEM_INIT(f) NULL
+#  define FT_FACE_FROM_PANGO_FONT(i,f,m) pango_fc_font_lock_face (PANGO_FC_FONT (f))
+#  define PANGO_FONT_RELEASE_FT_FACE(i,f) pango_fc_font_unlock_face (PANGO_FC_FONT (f))
+#  define RELEASE_EXTRA_FT_ITEMS(i)
+# endif
+#elif defined (GDK_WINDOWING_WIN32)
+
+# define FT_EXT_ITEM_INIT(f) g_new0 (gtk_win32_ft_items, 1)
+# define FT_FACE_FROM_PANGO_FONT(i,f,m) pangowin32_font_get_ftface (i, f, m)
+# define PANGO_FONT_RELEASE_FT_FACE(i,f) pangowin32_font_get_ftface_release_ftface (i)
+# define RELEASE_EXTRA_FT_ITEMS(i) release_extra_ft_items(i)
+#endif
+
+/* Until Pango uses HarfBuzz for shaping on all platforms, we need to go through FreeType */
+#ifdef GDK_WINDOWING_WIN32
+
+#include <pango/pangowin32.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_MODULE_H
+
+/* Check for TTC fonts and get their font data */
+# define FONT_TABLE_TTCF  (('t' << 0) + ('t' << 8) + ('c' << 16) + ('f' << 24))
+
+typedef struct _gtk_win32_ft_items
+{
+  FT_Library ft_lib;
+  FT_Byte *font_data_stream;
+  FT_Face face;
+  HDC hdc;
+  LOGFONTW *logfont;
+  HFONT hfont;
+  PangoWin32FontCache *cache;
+} gtk_win32_ft_items;
+
+#define WIN32_FT_FACE_FAIL(msg) \
+{ \
+  g_warning(msg); \
+  goto ft_face_fail; \
+}
+
+static FT_Face
+pangowin32_font_get_ftface (gtk_win32_ft_items *item,
+                            PangoFont          *font,
+                            PangoFontMap       *font_map)
+{
+  PangoWin32FontCache *cache = NULL;
+  LOGFONTW *logfont = NULL;
+  HFONT hfont = NULL;
+  HFONT hfont_orig = NULL;
+  HDC hdc = NULL;
+  DWORD is_ttc_font;
+  FT_Face face;
+  FT_Byte *font_stream = NULL;
+  unsigned char buf[4];
+  gsize font_size;
+
+  if (item == NULL)
+    item = g_new0 (gtk_win32_ft_items, 1);
+
+  cache = pango_win32_font_map_get_font_cache (font_map);
+
+  if (!cache)
+    WIN32_FT_FACE_FAIL ("Failed to acquire PangoWin32FontCache");
+
+  logfont = pango_win32_font_logfontw (font);
+
+  if (logfont == NULL)
+    WIN32_FT_FACE_FAIL ("Unable to acquire LOGFONT from PangoFont");
+
+  hfont = pango_win32_font_cache_loadw (cache, logfont);
+
+  if (hfont == NULL)
+    WIN32_FT_FACE_FAIL ("Unable to acquire HFONT from PangoWin32FontCache with LOGFONT (LOGFONT invalid?)");
+
+  hdc = GetDC (NULL);
+
+  if (hdc == NULL)
+    WIN32_FT_FACE_FAIL ("Failed to acquire DC");
+
+  if (item->ft_lib == NULL)
+    {
+      if (FT_Init_FreeType (&item->ft_lib) != FT_Err_Ok)
+        WIN32_FT_FACE_FAIL ("Failed to initialize FreeType for PangoWin32Font->FT_Face transformation");
+    }
+
+  hfont_orig = SelectObject (hdc, hfont);
+  if (hfont_orig == HGDI_ERROR)
+    WIN32_FT_FACE_FAIL ("SelectObject() for the PangoFont failed");
+
+  /* is_ttc_font is GDI_ERROR if the HFONT does not refer to a font in a TTC when,
+   * specifying FONT_TABLE_TTCF for the Font Table type, otherwise it is 1,
+   * so try again without specifying FONT_TABLE_TTCF if is_ttc_font is not 1
+   */
+  is_ttc_font = GetFontData (hdc, FONT_TABLE_TTCF, 0, &buf, 1);
+
+  if (is_ttc_font == 1)
+    font_size = GetFontData (hdc, FONT_TABLE_TTCF, 0, NULL, 0);
+  else
+    font_size = GetFontData (hdc, 0, 0, NULL, 0);
+
+  if (font_size == GDI_ERROR)
+    WIN32_FT_FACE_FAIL ("Could not acquire font size from GetFontData()");
+
+  /* Now, get the font data stream that we need for creating the FT_Face */
+  font_stream = g_malloc (font_size);
+  if (GetFontData (hdc,
+                   is_ttc_font == 1 ? FONT_TABLE_TTCF : 0,
+                   0,
+                   font_stream,
+                   font_size) == GDI_ERROR)
+    {
+      WIN32_FT_FACE_FAIL ("Unable to get data stream of font!");
+    }
+
+  /* Finally, create the FT_Face we need */
+  if (FT_New_Memory_Face (item->ft_lib,
+                          font_stream,
+                          font_size,
+                          0,
+                          &face) == FT_Err_Ok)
+    {
+      /* We need to track these because we can only release/free those items *after* we
+       * are done with them in FreeType
+       */
+      item->cache = cache;
+      item->logfont = logfont;
+      item->hdc = hdc;
+      item->hfont = hfont;
+      item->font_data_stream = font_stream;
+      item->face = face;
+      return item->face;
+    }
+
+  else
+    WIN32_FT_FACE_FAIL ("Unable to create FT_Face from font data stream!");
+
+ft_face_fail:
+  if (font_stream != NULL)
+    g_free (font_stream);
+
+  if (hdc != NULL)
+    ReleaseDC (NULL, hdc);
+
+  if (cache != NULL && hfont != NULL)
+    pango_win32_font_cache_unload (cache, hfont);
+
+  if (logfont != NULL)
+    g_free (logfont);
+
+  return NULL;
+}
+
+#undef WIN32_FT_FACE_FAIL
+
+static void
+pangowin32_font_get_ftface_release_ftface (gtk_win32_ft_items *item)
+{
+  FT_Done_Face (item->face);
+  g_free (item->font_data_stream);
+  ReleaseDC (NULL, item->hdc);
+  item->hdc = NULL;
+  pango_win32_font_cache_unload (item->cache, item->hfont);
+  g_free (item->logfont);
+}
+
+static gboolean
+release_extra_ft_items (gpointer *item)
+{
+  if (item != NULL)
+    {
+      gtk_win32_ft_items *ft_item = (gtk_win32_ft_items *) item;
+
+      if (ft_item->ft_lib != NULL)
+        FT_Done_Library (ft_item->ft_lib);
+
+      g_free (item);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+#endif /* GDK_WINDOWING_WIN32 */
\ No newline at end of file


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