summaryrefslogtreecommitdiff
path: root/pango/pangowin32.c
diff options
context:
space:
mode:
authorChun-wei Fan <fanchunwei@src.gnome.org>2019-07-16 18:40:31 +0800
committerMatthias Clasen <mclasen@redhat.com>2019-07-18 14:10:40 -0700
commit2a08070eb8db3132bea4c3d2ecd49e40c293e1a5 (patch)
tree4d75045d1dba24cd474022116893c9dcd8a64275 /pango/pangowin32.c
parent565ba1b218e964fec6ac2667b832a7d259fe6867 (diff)
downloadpango-2a08070eb8db3132bea4c3d2ecd49e40c293e1a5.tar.gz
win32: Implement create_hb_font
This renders correctly in ci. This attempts to acquire the hb_font_t from the HFont that we acquire from the Windows HFONT that we use, so that we can pass things to HarfBuzz, which will handle the shaping for us. win32: Set scale on hb font
Diffstat (limited to 'pango/pangowin32.c')
-rw-r--r--pango/pangowin32.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/pango/pangowin32.c b/pango/pangowin32.c
index 80abb0b4..0e877820 100644
--- a/pango/pangowin32.c
+++ b/pango/pangowin32.c
@@ -35,6 +35,7 @@
#include <string.h>
#include <stdlib.h>
#include <glib.h>
+#include <hb.h>
#include "pango-impl-utils.h"
#include "pangowin32.h"
@@ -86,6 +87,8 @@ static void pango_win32_get_item_properties (PangoItem
PangoAttrColor *bg_color,
gboolean *bg_set);
+static hb_font_t * pango_win32_font_create_hb_font (PangoFont *font);
+
HFONT
_pango_win32_font_get_hfont (PangoFont *font)
{
@@ -207,6 +210,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class)
font_class->get_glyph_extents = pango_win32_font_get_glyph_extents;
font_class->get_metrics = pango_win32_font_get_metrics;
font_class->get_font_map = pango_win32_font_get_font_map;
+ font_class->create_hb_font = pango_win32_font_create_hb_font;
class->select_font = pango_win32_font_real_select_font;
class->done_font = pango_win32_font_real_done_font;
@@ -1909,3 +1913,84 @@ pango_win32_font_calc_coverage (PangoFont *font,
g_print ("\n");
#endif
}
+
+/*
+ * Swap HarfBuzz-style tags to tags that GetFontData() understands,
+ * adapted from https://github.com/harfbuzz/harfbuzz/pull/1832,
+ * by Ebrahim Byagowi.
+ */
+
+static inline guint16 hb_gdi_uint16_swap (const guint16 v)
+{ return (v >> 8) | (v << 8); }
+static inline guint32 hb_gdi_uint32_swap (const guint32 v)
+{ return (hb_gdi_uint16_swap (v) << 16) | hb_gdi_uint16_swap (v >> 16); }
+
+/*
+ * Adapted from https://www.mail-archive.com/harfbuzz@lists.freedesktop.org/msg06538.html
+ * by Konstantin Ritt.
+ */
+static hb_blob_t *
+hfont_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+{
+ HDC hdc;
+ HFONT hfont, old_hfont;
+ gchar *buf = NULL;
+ DWORD size;
+
+ /* We have a common DC for our PangoWin32Font, so let's just use it */
+ hdc = pango_win32_get_dc ();
+ hfont = (HFONT) user_data;
+
+ /* we want to restore things, just to be safe */
+ old_hfont = SelectObject (hdc, hfont);
+ if (old_hfont == NULL)
+ {
+ g_warning ("SelectObject() for the PangoWin32Font failed!");
+ return hb_blob_get_empty ();
+ }
+
+ size = GetFontData (hdc, hb_gdi_uint32_swap (tag), 0, NULL, 0);
+
+ /*
+ * not all tags support retrieving the sizes, so don't warn,
+ * just return hb_blob_get_empty()
+ */
+ if (size == GDI_ERROR)
+ {
+ SelectObject (hdc, old_hfont);
+ return hb_blob_get_empty ();
+ }
+
+ buf = g_malloc (size * sizeof (gchar));
+
+ /* This should be quite unlikely to fail if size was not GDI_ERROR */
+ if (GetFontData (hdc, hb_gdi_uint32_swap (tag), 0, buf, size) == GDI_ERROR)
+ size = 0;
+
+ SelectObject (hdc, old_hfont);
+ return hb_blob_create (buf, size, HB_MEMORY_MODE_READONLY, buf, g_free);
+}
+
+static hb_font_t *
+pango_win32_font_create_hb_font (PangoFont *font)
+{
+ PangoWin32Font *win32font = (PangoWin32Font *)font;
+ HFONT hfont;
+ hb_face_t *face = NULL;
+ hb_font_t *hb_font = NULL;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ hfont = _pango_win32_font_get_hfont (font);
+
+ /* We are *not* allowed to destroy the HFONT here ! */
+ face = hb_face_create_for_tables (hfont_reference_table, (void *)hfont, NULL);
+
+ hb_font = hb_font_create (face);
+ hb_font_set_scale (hb_font, win32font->size, win32font->size);
+ hb_face_destroy (face);
+
+ hb_font_make_immutable (hb_font);
+
+ return hb_font;
+}