[gtk/wip/fanc999/fontchooser.win32.gtk3: 4/8] gtk: Add utility source to convert from PangoFont to FT_Face



commit 8946b61881b2f6d4c3778a8e3dee098807258d51
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Mon Jan 7 13:20:48 2019 +0800

    gtk: Add utility source to convert from PangoFont to FT_Face
    
    ...when we are not using PangoFT2, so that we can continue using
    HarfBuzz to query the OpenType tags for use with font tweaking, at least
    before Pango uses HarfBuzz to shape on all platforms.

 gtk/Makefile.am                |   2 +
 gtk/gtkpangofontutils.c        | 265 +++++++++++++++++++++++++++++++++++++++++
 gtk/gtkpangofontutilsprivate.h |  37 ++++++
 3 files changed, 304 insertions(+)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 559442963e..09823b7d3f 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -535,6 +535,7 @@ gtk_private_h_sources =             \
        gtknativedialogprivate.h \
        gtkorientableprivate.h  \
        gtkpango.h              \
+       gtkpangofontutilsprivate.h      \
        gtkpathbar.h            \
        gtkplacessidebarprivate.h       \
        gtkplacesviewprivate.h  \
@@ -859,6 +860,7 @@ gtk_base_c_sources =                \
        gtkpagesetup.c          \
        gtkpaned.c              \
        gtkpango.c              \
+       gtkpangofontutils.c     \
        gtkpapersize.c          \
        gtkpathbar.c            \
        gtkplacessidebar.c      \
diff --git a/gtk/gtkpangofontutils.c b/gtk/gtkpangofontutils.c
new file mode 100644
index 0000000000..8e0e94215d
--- /dev/null
+++ b/gtk/gtkpangofontutils.c
@@ -0,0 +1,265 @@
+/* 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/>.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_HARFBUZZ
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_MODULE_H
+
+#include "gtkpangofontutilsprivate.h"
+
+#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 G_OS_WIN32
+#  define FT_EXT_ITEM_INIT(f)   \
+          PANGO_IS_FC_FONT(f) ? \
+          NULL : \
+          g_new0 (gtk_win32_ft_items, 1)
+
+#  define PANGO_FONT_GET_FT_FACE(f,m,i) \
+          PANGO_IS_FC_FONT(f) ?          \
+          pango_fc_font_lock_face (PANGO_FC_FONT (f)) : \
+          pangowin32_font_get_ftface (f, m, i)
+
+#  define PANGO_FONT_RELEASE_FT_FACE(f,i) \
+          PANGO_IS_FC_FONT(f) ?           \
+          pango_fc_font_unlock_face (PANGO_FC_FONT (f)) : \
+          pangowin32_font_release_ftface (i);
+
+#  define RELEASE_EXTRA_FT_ITEMS(i) pangowin32_font_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 PANGO_FONT_GET_FT_FACE(f,m,i) pango_fc_font_lock_face (PANGO_FC_FONT (f))
+#  define PANGO_FONT_RELEASE_FT_FACE(f,i) pango_fc_font_unlock_face (PANGO_FC_FONT (f))
+#  define RELEASE_EXTRA_FT_ITEMS(i) FALSE
+# endif
+#elif defined (G_OS_WIN32) /* HAVE_PANGOFT */
+
+/* Until Pango uses HarfBuzz for shaping on all platforms, we need to go through FreeType */
+
+# define FT_EXT_ITEM_INIT(f) g_new0 (gtk_win32_ft_items, 1)
+# define PANGO_FONT_GET_FT_FACE(f,m,i) pangowin32_font_get_ftface (f, m, i)
+# define PANGO_FONT_RELEASE_FT_FACE(f,i) pangowin32_font_release_ftface (i)
+# define RELEASE_EXTRA_FT_ITEMS(i) pangowin32_font_release_extra_ft_items(i)
+
+#endif /* G_OS_WIN32 */
+
+/* Note: The following is for both builds with and without PangoFT support on Windows */
+#ifdef G_OS_WIN32
+#include <pango/pangowin32.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 (PangoFont          *font,
+                            PangoFontMap       *font_map,
+                            gtk_win32_ft_items *item)
+{
+  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_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);
+}
+
+gboolean
+pangowin32_font_release_extra_ft_items (gpointer ft_item)
+{
+  gtk_win32_ft_items *item = NULL;
+
+  if (ft_item == NULL)
+    return FALSE;
+
+  item = (gtk_win32_ft_items *)ft_item;
+  if (item->ft_lib != NULL)
+    {
+      FT_Done_Library (item->ft_lib);
+      item->ft_lib = NULL;
+    }
+
+  return TRUE;
+
+}
+
+#endif /* G_OS_WIN32 */
+
+gpointer
+_gtk_pango_font_init_extra_ft_items (PangoFont *font)
+{
+  return FT_EXT_ITEM_INIT (font);
+}
+
+FT_Face
+_gtk_pango_font_get_ft_face (PangoFont    *font,
+                             PangoFontMap *font_map,
+                             gpointer      ft_items)
+{
+  return PANGO_FONT_GET_FT_FACE (font, font_map, ft_items);
+}
+
+void
+_gtk_pango_font_release_ft_face (PangoFont *font,
+                                 gpointer   ft_items)
+{
+  PANGO_FONT_RELEASE_FT_FACE (font, ft_items);
+}
+
+gboolean
+_gtk_pango_font_release_ft_items (gpointer ft_items)
+{
+  return RELEASE_EXTRA_FT_ITEMS (ft_items);
+}
+#endif /* HAVE_HARFBUZZ */
diff --git a/gtk/gtkpangofontutilsprivate.h b/gtk/gtkpangofontutilsprivate.h
new file mode 100644
index 0000000000..4b0a7aae8f
--- /dev/null
+++ b/gtk/gtkpangofontutilsprivate.h
@@ -0,0 +1,37 @@
+/* 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/>.
+ */
+
+#ifndef __GTK_PANGO_FONT_UTILS_PRIVATE_H__
+#define __GTK_PANGO_FONT_UTILS_PRIVATE_H__
+
+#include <pango/pango.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+gpointer _gtk_pango_font_init_extra_ft_items (PangoFont    *font);
+
+FT_Face  _gtk_pango_font_get_ft_face         (PangoFont    *font,
+                                              PangoFontMap *font_map,
+                                              gpointer      ft_items);
+
+void     _gtk_pango_font_release_ft_face     (PangoFont    *font,
+                                              gpointer      ft_items);
+
+gboolean _gtk_pango_font_release_ft_items    (gpointer      ft_items);
+
+#endif /* __GTK_PANGO_FONT_UTILS_PRIVATE_H__ */


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