public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Takao Fujiwara <tfujiwar@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/ibus] autotool: Delete ibus-xx-emoji-harfbuzz.patch
Date: Sun, 31 May 2026 02:06:52 GMT [thread overview]
Message-ID: <178019321231.1.13345828956723386725.rpms-ibus-3bca2d162b45@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/ibus
Branch : autotool
Commit : 3bca2d162b45cec3bdd1ff0fa31c98d8442f0bba
Author : Takao Fujiwara <tfujiwar@redhat.com>
Date : 2018-06-20T19:09:12+09:00
Stats : +0/-1764 in 1 file(s)
URL : https://src.fedoraproject.org/rpms/ibus/c/3bca2d162b45cec3bdd1ff0fa31c98d8442f0bba?branch=autotool
Log:
Delete ibus-xx-emoji-harfbuzz.patch
---
diff --git a/ibus-xx-emoji-harfbuzz.patch b/ibus-xx-emoji-harfbuzz.patch
deleted file mode 100644
index 15d1a05..0000000
--- a/ibus-xx-emoji-harfbuzz.patch
+++ /dev/null
@@ -1,1764 +0,0 @@
-From 631ef573ebdd4f3fad8f036fcb33929e04372ab2 Mon Sep 17 00:00:00 2001
-From: fujiwarat <takao.fujiwara1@gmail.com>
-Date: Thu, 1 Mar 2018 16:05:04 +0900
-Subject: [PATCH] Integrate custom rendering to use HarfBuzz glyph info
-
-IBusFontSet offers FcFontSet, glyph info with HarfBuzz and rendering
-on Cairo context.
-Now the most issues in Pango were fixed and I appreciate the changes [1].
-However the latest changes in Pango, Fontconfig prevent users from
-setting emoji fonts with GtkFontChooser.
-This patch can enable the selected emoji font to draw emoji chars
-on Emojier.
-It's under the considerations if the font setting is deleted from ibus-setup.
-Need configure --enable-harfbuzz-for-emoji option to enable this feature.
-
-[1]: https://bugzilla.gnome.org/show_bug.cgi?id=780669
- https://bugzilla.gnome.org/show_bug.cgi?id=781123
----
- bindings/vala/IBusFontSet-1.0.metadata | 1 +
- bindings/vala/Makefile.am | 83 +++
- bindings/vala/ibus-fontset-1.0.deps | 1 +
- configure.ac | 29 +
- ui/gtk3/Makefile.am | 36 ++
- ui/gtk3/emojier.vala | 111 ++++
- ui/gtk3/ibusfontset.c | 1030 ++++++++++++++++++++++++++++++++
- ui/gtk3/ibusfontset.h | 302 ++++++++++
- 8 files changed, 1593 insertions(+)
- create mode 100644 bindings/vala/IBusFontSet-1.0.metadata
- create mode 100644 bindings/vala/ibus-fontset-1.0.deps
- create mode 100644 ui/gtk3/ibusfontset.c
- create mode 100644 ui/gtk3/ibusfontset.h
-
-diff --git a/bindings/vala/IBusFontSet-1.0.metadata b/bindings/vala/IBusFontSet-1.0.metadata
-new file mode 100644
-index 00000000..73037d7f
---- /dev/null
-+++ b/bindings/vala/IBusFontSet-1.0.metadata
-@@ -0,0 +1 @@
-+IBusFontSet cheader_filename="ibusfontset.h"
-diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am
-index fc8e2f01..f7b9e97a 100644
---- a/bindings/vala/Makefile.am
-+++ b/bindings/vala/Makefile.am
-@@ -83,8 +83,10 @@ EXTRA_DIST = \
- IBus-1.0.metadata \
- IBus-1.0-custom.vala \
- IBusEmojiDialog-1.0.metadata \
-+ IBusFontSet-1.0.metadata \
- ibus-1.0.deps \
- ibus-emoji-dialog-1.0.deps \
-+ ibus-fontset-1.0.deps \
- config.vapi \
- xi.vapi \
- $(NULL)
-@@ -131,6 +133,15 @@ libibus_emoji_dialog_1_0_la_LDFLAGS = \
- if test ! -f $@ ; then \
- $(LN_S) $(top_srcdir)/ui/gtk3/$@ .; \
- fi;
-+ibusfontset.c: $(ibus_vapi) ibusfontset.h
-+ if test ! -f $@ ; then \
-+ $(LN_S) $(top_srcdir)/ui/gtk3/$@ .; \
-+ fi;
-+ibusfontset.h: $(ibus_vapi)
-+ if test ! -f $@ ; then \
-+ $(LN_S) $(top_srcdir)/ui/gtk3/$@ .; \
-+ fi;
-+
-
- MAINTAINERCLEANFILES += $(libibus_emoji_dialog_1_0_la_SOURCES)
- DISTCLEANFILES += $(libibus_emoji_dialog_1_0_la_SOURCES)
-@@ -184,6 +195,78 @@ DISTCLEANFILES += $(ibus_emoji_dialog_vapi)
-
- endif
- #end of HAVE_INTROSPECTION
-+
-+
-+if ENABLE_HARFBUZZ_FOR_EMOJI
-+libibus_fontset = libibus-fontset-1.0.la
-+noinst_LTLIBRARIES += $(libibus_fontset)
-+
-+libibus_fontset_1_0_la_SOURCES = \
-+ ibusfontset.c \
-+ $(NULL)
-+libibus_fontset_1_0_la_CFLAGS = \
-+ $(AM_CFLAGS) \
-+ @CAIRO_CFLAGS@ \
-+ @FONTCONFIG_CFLAGS@ \
-+ @GLIB2_CFLAGS@ \
-+ @HARFBUZZ_CFLAGS@ \
-+ @PANGO_CFLAGS@ \
-+ $(NULL)
-+libibus_fontset_1_0_la_LIBADD = \
-+ @CAIRO_LIBS@ \
-+ @FONTCONFIG_LIBS@ \
-+ @GLIB2_LIBS@ \
-+ @HARFBUZZ_LIBS@ \
-+ @PANGO_LIBS@ \
-+ $(NULL)
-+libibus_fontset_1_0_la_LDFLAGS = \
-+ -no-undefined \
-+ -export-symbols-regex "ibus_.*" \
-+ $(NULL)
-+
-+MAINTAINERCLEANFILES += ibusfontset.c ibusfontset.h
-+DISTCLEANFILES += ibusfontset.c ibusfontset.h
-+
-+if HAVE_INTROSPECTION
-+IBusFontSet-1.0.gir: $(libibus_fontset) Makefile
-+IBusFontSet_1_0_gir_SCANNERFLAGS = \
-+ --pkg-export=ibus-1.0 \
-+ --pkg=cairo \
-+ --pkg=fontconfig \
-+ --pkg=harfbuzz \
-+ $(IBUS_GIR_SCANNERFLAGS) \
-+ $(NULL)
-+IBusFontSet_1_0_gir_LIBS = $(libibus_fontset) $(libibus)
-+IBusFontSet_1_0_gir_INCLUDES = cairo-1.0 GLib-2.0 GObject-2.0
-+IBusFontSet_1_0_gir_FILES = \
-+ ibusfontset.h \
-+ $(NULL)
-+IBusFontSet_1_0_gir_CFLAGS = \
-+ -I$(srcdir) \
-+ -I$(builddir) \
-+ -I$(top_srcdir)/src \
-+ $(NULL)
-+ibus_fontset_gir = IBusFontSet-1.0.gir
-+INTROSPECTION_GIRS += $(ibus_fontset_gir)
-+noinst_DATA += $(ibus_fontset_gir)
-+EXTRA_DIST += $(ibus_fontset_gir)
-+MAINTAINERCLEANFILES += $(ibus_fontset_gir)
-+DISTCLEANFILES += $(ibus_fontset_gir)
-+
-+ibus-fontset-1.0.vapi: $(ibus_fontset_gir) IBusFontSet-1.0.metadata
-+ibus_fontset_vapi = ibus-fontset-1.0.vapi
-+ibus_fontset_1_0_vapi_METADATADIRS = $(srcdir)
-+ibus_fontset_1_0_vapi_FILES = IBusFontSet-1.0.gir
-+VAPIGEN_VAPIS += $(ibus_fontset_vapi)
-+noinst_DATA += $(ibus_fontset_vapi)
-+EXTRA_DIST += $(ibus_fontset_vapi)
-+MAINTAINERCLEANFILES += $(ibus_fontset_vapi)
-+DISTCLEANFILES += $(ibus_fontset_vapi)
-+
-+endif
-+# end of HAVE_INTROSPECTION
-+endif
-+# end of ENABLE_HARFBUZZ_FOR_EMOJI
- endif
- # end of ENABLE_EMOJI_DICT
-
-diff --git a/bindings/vala/ibus-fontset-1.0.deps b/bindings/vala/ibus-fontset-1.0.deps
-new file mode 100644
-index 00000000..129fe166
---- /dev/null
-+++ b/bindings/vala/ibus-fontset-1.0.deps
-@@ -0,0 +1 @@
-+cairo
-diff --git a/configure.ac b/configure.ac
-index bd41069b..243396ff 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -688,6 +688,34 @@ the UCD files from https://www.unicode.org/Public/UNIDATA/)
- enable_unicode_dict="yes (enabled, use --disable-unicode-dict to disable)"
- fi
-
-+AC_ARG_ENABLE(harfbuzz-for-emoji,
-+ AS_HELP_STRING([--enable-harfbuzz-for-emoji],
-+ [Enable HarBuzz to draw emoji characters.
-+ Current Pango has a problem to draw emoji variants and
-+ this way enables to use HarfBuzz directly in GtkLabel.]),
-+ [enable_harfbuzz_for_emoji=$enableval],
-+ [enable_harfbuzz_for_emoji=no]
-+)
-+AM_CONDITIONAL([ENABLE_HARFBUZZ_FOR_EMOJI],
-+ [test x"$enable_harfbuzz_for_emoji" = x"yes"])
-+
-+if test x"$enable_harfbuzz_for_emoji" = x"yes"; then
-+ PKG_CHECK_MODULES(CAIRO, [
-+ cairo
-+ ])
-+ PKG_CHECK_MODULES(FONTCONFIG, [
-+ fontconfig
-+ ])
-+ PKG_CHECK_MODULES(HARFBUZZ, [
-+ harfbuzz
-+ ])
-+ PKG_CHECK_MODULES(PANGO, [
-+ pango
-+ ])
-+else
-+ enable_harfbuzz_for_emoji="no (disabled, use --enable-harfbuzz-for-emoji to enable)"
-+fi
-+
- # Check iso-codes.
- PKG_CHECK_MODULES(ISOCODES, [
- iso-codes
-@@ -780,6 +808,7 @@ Build options:
- CLDR annotation directory $EMOJI_ANNOTATION_DIR
- Enable Unicode dict $enable_unicode_dict
- UCD directory $UCD_DIR
-+ Enable HarfBuzz for Emoji $enable_harfbuzz_for_emoji
- Run test cases $enable_tests
- ])
-
-diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
-index bf9f98d7..388f80f9 100644
---- a/ui/gtk3/Makefile.am
-+++ b/ui/gtk3/Makefile.am
-@@ -159,6 +159,8 @@ EXTRA_DIST = \
- extension.vala \
- gtkextension.xml.in \
- gtkpanel.xml.in \
-+ ibusfontset.c \
-+ ibusfontset.h \
- notification-item.xml \
- notification-watcher.xml \
- ibus-ui-emojier.desktop.in.in \
-@@ -249,6 +251,40 @@ panelbinding.o: $(srcdir)/panelbinding.c
- $(AM_V_CC_no)$(COMPILE) -c -o $@ $<
- $(NULL)
-
-+if ENABLE_HARFBUZZ_FOR_EMOJI
-+ibus_ui_gtk3_SOURCES += \
-+ ibusfontset.c \
-+ $(NULL)
-+
-+ibus_ui_emojier_SOURCES += \
-+ ibusfontset.c \
-+ $(NULL)
-+
-+ibus_extension_gtk3_SOURCES += \
-+ ibusfontset.c \
-+ $(NULL)
-+
-+AM_CFLAGS += \
-+ @CAIRO_CFLAGS@ \
-+ @FONTCONFIG_CFLAGS@ \
-+ @HARFBUZZ_CFLAGS@ \
-+ $(NULL)
-+
-+AM_LDADD += \
-+ @CAIRO_LIBS@ \
-+ @FONTCONFIG_LIBS@ \
-+ @HARFBUZZ_LIBS@ \
-+ $(NULL)
-+
-+AM_VALAFLAGS += \
-+ -D ENABLE_HARFBUZZ_FOR_EMOJI \
-+ --pkg=cairo \
-+ --pkg=ibus-fontset-1.0 \
-+ $(NULL)
-+
-+endif
-+# end of ENABLE_HARFBUZZ_FOR_EMOJI
-+
- man_seven_files = $(man_seven_in_files:.7.in=.7)
- man_seven_DATA =$(man_seven_files:.7=.7.gz)
- man_sevendir = $(mandir)/man7
-diff --git a/ui/gtk3/emojier.vala b/ui/gtk3/emojier.vala
-index 8707e432..49619d1c 100644
---- a/ui/gtk3/emojier.vala
-+++ b/ui/gtk3/emojier.vala
-@@ -99,16 +99,103 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
- }
- private class EWhiteLabel : Gtk.Label {
-+#if ENABLE_HARFBUZZ_FOR_EMOJI
-+ private IBus.RequisitionEx m_requisition;
-+#else
- private int m_minimum_width = 0;
- private int m_natural_width = 0;
- private int m_minimum_height = 0;
- private int m_natural_height = 0;
-+#endif
- public EWhiteLabel(string text) {
- GLib.Object(
- name : "IBusEmojierWhiteLabel"
- );
- set_label(text);
- }
-+#if ENABLE_HARFBUZZ_FOR_EMOJI
-+ private void get_preferred_size_with_hb(out int minimum_width,
-+ out int natural_width,
-+ out int minimum_height,
-+ out int natural_height) {
-+ minimum_width = 0;
-+ natural_width = 0;
-+ minimum_height = 0;
-+ natural_height = 0;
-+ var text = this.get_text();
-+ GLib.return_if_fail (text != null);
-+ if (text == "")
-+ return;
-+ var context = this.get_pango_context();
-+ var language = context.get_language();
-+ update_fontset(language);
-+ Cairo.RectangleInt widest = Cairo.RectangleInt();
-+ m_requisition = m_fontset.get_preferred_size_hb(text, out widest);
-+ minimum_width = widest.width;
-+ natural_width = widest.width;
-+ minimum_height = widest.height;
-+ natural_height = widest.height;
-+ if (minimum_width <= minimum_height)
-+ natural_width = minimum_width = minimum_height;
-+ if (text.length == 1) {
-+ switch(text.get_char()) {
-+ case '\t':
-+ natural_width = minimum_width = minimum_height;
-+ break;
-+ case '\v':
-+ natural_height = minimum_height = minimum_width;
-+ break;
-+ }
-+ }
-+ }
-+ public override void get_preferred_width(out int minimum_width,
-+ out int natural_width) {
-+ get_preferred_size_with_hb(out minimum_width,
-+ out natural_width,
-+ null, null);
-+ }
-+ public override void get_preferred_height(out int minimum_height,
-+ out int natural_height) {
-+ get_preferred_size_with_hb(null, null,
-+ out minimum_height,
-+ out natural_height);
-+ }
-+ public override bool draw(Cairo.Context cr) {
-+ var style_context = get_style_context();
-+ Gtk.Allocation allocation;
-+ get_allocation(out allocation);
-+ style_context.render_background(cr,
-+ 0, 0,
-+ allocation.width,
-+ allocation.height);
-+ if (m_fontset == null)
-+ return true;
-+ if (m_requisition == null)
-+ return true;
-+ if (m_requisition.cairo_lines == null)
-+ return true;
-+ Gdk.RGBA *normal_fg = null;
-+ style_context.get(Gtk.StateFlags.NORMAL,
-+ "color",
-+ out normal_fg);
-+ cr.set_operator(Cairo.Operator.OVER);
-+ cr.set_source_rgba(normal_fg.red, normal_fg.green, normal_fg.blue,
-+ normal_fg.alpha);
-+ cr.save();
-+ double x = 0.0;
-+ double y = 0.0;
-+ if (allocation.width > m_requisition.width)
-+ x = (allocation.width - m_requisition.width) / 2.0;
-+ if (allocation.height > m_requisition.height)
-+ y = (allocation.height - m_requisition.height) / 2.0;
-+ cr.translate(x, y);
-+ m_fontset.draw_cairo_with_requisition_ex(cr, m_requisition);
-+ cr.restore();
-+ normal_fg.free();
-+ normal_fg = null;
-+ return true;
-+ }
-+#else
- public override void get_preferred_width(out int minimum_width,
- out int natural_width) {
- if (m_minimum_height == 0 && m_natural_height == 0) {
-@@ -161,6 +248,7 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- m_minimum_height = minimum_height;
- m_natural_height = natural_height;
- }
-+#endif
- }
- private class ESelectedLabel : EWhiteLabel {
- public ESelectedLabel(string text) {
-@@ -313,6 +401,9 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- private static bool m_show_unicode = false;
- private static LoadProgressObject m_unicode_progress_object;
- private static bool m_loaded_unicode = false;
-+#if ENABLE_HARFBUZZ_FOR_EMOJI
-+ private static IBus.FontSet m_fontset;
-+#endif
-
- private ThemedRGBA m_rgba;
- private Gtk.Box m_vbox;
-@@ -2116,6 +2207,22 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- }
-
-
-+#if ENABLE_HARFBUZZ_FOR_EMOJI
-+ private static void update_fontset(Pango.Language language) {
-+ if (m_fontset != null) {
-+ m_fontset.set_family(m_emoji_font_family);
-+ m_fontset.set_size(m_emoji_font_size);
-+ m_fontset.set_language(language.to_string());
-+ m_fontset.update_fcfontset();
-+ } else {
-+ m_fontset = new IBus.FontSet.with_font(
-+ m_emoji_font_family,
-+ m_emoji_font_size,
-+ language.to_string());
-+ }
-+ }
-+#endif
-+
- public static bool has_loaded_emoji_dict() {
- if (m_emoji_to_data_dict == null)
- return false;
-@@ -2146,6 +2253,10 @@ public class IBusEmojier : Gtk.ApplicationWindow {
- int font_size = font_desc.get_size() / Pango.SCALE;
- if (font_size != 0)
- m_emoji_font_size = font_size;
-+#if ENABLE_HARFBUZZ_FOR_EMOJI
-+ var widget = new Gtk.Label("");
-+ update_fontset(widget.get_pango_context().get_language());
-+#endif
- }
-
-
-diff --git a/ui/gtk3/ibusfontset.c b/ui/gtk3/ibusfontset.c
-new file mode 100644
-index 00000000..16ceef05
---- /dev/null
-+++ b/ui/gtk3/ibusfontset.c
-@@ -0,0 +1,1030 @@
-+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-+/* vim:set et sts=4: */
-+/* ibus - The Input Bus
-+ * Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2017 Red Hat, Inc.
-+ *
-+ * 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.1 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, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
-+ * USA
-+ */
-+
-+#include <cairo-ft.h>
-+#include <fontconfig/fontconfig.h>
-+#include <ft2build.h>
-+#include FT_FREETYPE_H
-+#include <glib.h>
-+#include <hb-ot.h>
-+#include <pango/pango.h>
-+
-+#include "ibusfontset.h"
-+
-+#define XPAD 2
-+#define YPAD 2
-+#define UNKNOWN_FONT_SIZE 7
-+#define IBUS_FONTSET_GET_PRIVATE(o) \
-+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FONTSET, IBusFontSetPrivate))
-+#define MONOSPACE "monospace"
-+#define SERIF "serif"
-+#define SANS "sans"
-+
-+typedef struct _FcFontSetEx {
-+ int nfont;
-+ int sfont;
-+ FcPattern **fonts;
-+ FT_Face *ft_faces;
-+} FcFontSetEx;
-+
-+static gboolean m_color_supported;
-+static FT_Library m_ftlibrary;
-+static FcFontSetEx *m_fcfontset;
-+static gchar *m_family;
-+static guint m_size;
-+static gchar *m_language;
-+static GHashTable *m_font_index_per_char_table;
-+static GHashTable *m_scaled_font_table;
-+static GHashTable *m_hb_font_table;
-+
-+enum {
-+ PROP_0,
-+ PROP_FAMILY,
-+ PROP_SIZE,
-+ PROP_LANGUAGE
-+};
-+
-+typedef struct {
-+ gunichar ch;
-+ FcPattern *fcfont;
-+} FontPerChar;
-+
-+struct _IBusFontSetPrivate {
-+ gchar *family;
-+ guint size;
-+ gchar *language;
-+};
-+
-+static GObject * ibus_fontset_constructor (GType type,
-+ guint n,
-+ GObjectConstructParam *args);
-+static void ibus_fontset_destroy (IBusFontSet *fontset);
-+static void ibus_fontset_set_property (IBusFontSet *fontset,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec);
-+static void ibus_fontset_get_property (IBusFontSet *fontset,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec);
-+static cairo_scaled_font_t *
-+ ibus_fontset_cairo_scaled_font_new_with_font
-+ (const gchar *family,
-+ guint size,
-+ gboolean has_color);
-+
-+G_DEFINE_BOXED_TYPE (IBusCairoLine,
-+ ibus_cairo_line,
-+ ibus_cairo_line_copy,
-+ ibus_cairo_line_free);
-+G_DEFINE_BOXED_TYPE (IBusRequisitionEx,
-+ ibus_requisition_ex,
-+ ibus_requisition_ex_copy,
-+ ibus_requisition_ex_free);
-+G_DEFINE_TYPE (IBusFontSet, ibus_fontset, IBUS_TYPE_OBJECT)
-+
-+static void
-+ibus_fontset_class_init (IBusFontSetClass *class)
-+{
-+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
-+ IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
-+ cairo_glyph_t dummy;
-+ IBusGlyph dummy2;
-+
-+ m_color_supported = (FcGetVersion () >= 21205);
-+ gobject_class->constructor = ibus_fontset_constructor;
-+ gobject_class->get_property =
-+ (GObjectGetPropertyFunc) ibus_fontset_get_property;
-+ gobject_class->set_property =
-+ (GObjectSetPropertyFunc) ibus_fontset_set_property;
-+ object_class->destroy = (IBusObjectDestroyFunc) ibus_fontset_destroy;
-+
-+ /* install properties */
-+ /**
-+ * IBusFontSet:family:
-+ *
-+ * Font family of this IBusFontSet.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_FAMILY,
-+ g_param_spec_string ("family",
-+ "family",
-+ "family",
-+ "",
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-+
-+ /**
-+ * IBusFontSet:size:
-+ *
-+ * Font size of this IBusFontSet.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_SIZE,
-+ g_param_spec_uint ("size",
-+ "size",
-+ "size",
-+ 0, G_MAXUINT16, 0,
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-+
-+ /**
-+ * IBusFontSet:language:
-+ *
-+ * Font language of this IBusFontSet.
-+ */
-+ g_object_class_install_property (gobject_class,
-+ PROP_LANGUAGE,
-+ g_param_spec_string ("language",
-+ "language",
-+ "language",
-+ "",
-+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-+
-+ g_type_class_add_private (class, sizeof (IBusFontSetPrivate));
-+ FT_Init_FreeType (&m_ftlibrary);
-+ m_scaled_font_table = g_hash_table_new_full (
-+ g_str_hash, g_str_equal,
-+ g_free,
-+ (GDestroyNotify) cairo_scaled_font_destroy);
-+ m_hb_font_table = g_hash_table_new_full (
-+ g_str_hash, g_str_equal,
-+ g_free,
-+ (GDestroyNotify) hb_font_destroy);
-+
-+ /* hb_glyph_t is not available in Vala so override it with IBusGlyph. */
-+ g_assert (sizeof (dummy) == sizeof (dummy2));
-+ g_assert (sizeof (dummy.index) == sizeof (dummy2.index));
-+ g_assert (sizeof (dummy.x) == sizeof (dummy2.x));
-+ g_assert (sizeof (dummy.y) == sizeof (dummy2.y));
-+}
-+
-+static void
-+ibus_fontset_init (IBusFontSet *fontset)
-+{
-+ fontset->priv = IBUS_FONTSET_GET_PRIVATE (fontset);
-+}
-+
-+
-+static GObject *
-+ibus_fontset_constructor (GType type,
-+ guint n,
-+ GObjectConstructParam *args)
-+{
-+ GObject *object;
-+ IBusFontSet *fontset;
-+ const gchar *family;
-+ guint size;
-+
-+ object = G_OBJECT_CLASS (ibus_fontset_parent_class)->constructor (
-+ type, n ,args);
-+ fontset = IBUS_FONTSET (object);
-+ family = ibus_fontset_get_family (fontset);
-+ size = ibus_fontset_get_size (fontset);
-+ ibus_fontset_update_fcfontset (fontset);
-+ if (family != NULL && size > 0) {
-+ /* cache the font */
-+ ibus_fontset_cairo_scaled_font_new_with_font (family,
-+ size,
-+ TRUE);
-+ }
-+ return object;
-+}
-+
-+static void
-+ibus_fontset_destroy (IBusFontSet *fontset)
-+{
-+ g_clear_pointer (&fontset->priv->family, g_free);
-+ g_clear_pointer (&fontset->priv->language, g_free);
-+}
-+
-+static void
-+ibus_fontset_set_property (IBusFontSet *fontset,
-+ guint prop_id,
-+ const GValue *value,
-+ GParamSpec *pspec)
-+{
-+ switch (prop_id) {
-+ case PROP_FAMILY:
-+ ibus_fontset_set_family (fontset, g_value_get_string (value));
-+ break;
-+ case PROP_SIZE:
-+ ibus_fontset_set_size (fontset, g_value_get_uint (value));
-+ break;
-+ case PROP_LANGUAGE:
-+ ibus_fontset_set_language (fontset, g_value_get_string (value));
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (fontset, prop_id, pspec);
-+ }
-+}
-+
-+static void
-+ibus_fontset_get_property (IBusFontSet *fontset,
-+ guint prop_id,
-+ GValue *value,
-+ GParamSpec *pspec)
-+{
-+ switch (prop_id) {
-+ case PROP_FAMILY:
-+ g_value_set_string (value, ibus_fontset_get_family (fontset));
-+ break;
-+ case PROP_SIZE:
-+ g_value_set_uint (value, ibus_fontset_get_size (fontset));
-+ break;
-+ case PROP_LANGUAGE:
-+ g_value_set_string (value, ibus_fontset_get_language (fontset));
-+ break;
-+ default:
-+ G_OBJECT_WARN_INVALID_PROPERTY_ID (fontset, prop_id, pspec);
-+ }
-+}
-+
-+static cairo_scaled_font_t *
-+ibus_fontset_cairo_scaled_font_new_with_font (const gchar *family,
-+ guint size,
-+ gboolean has_color)
-+{
-+ gchar *font_name;
-+ cairo_scaled_font_t *scaled_font = NULL;
-+ FcPattern *pattern, *resolved;
-+ FcResult result;
-+ cairo_font_options_t *font_options;
-+ double pixel_size = 0.;
-+ FcMatrix fc_matrix, *fc_matrix_val;
-+ cairo_font_face_t *cairo_face = NULL;
-+ cairo_matrix_t font_matrix;
-+ cairo_matrix_t ctm;
-+ int i;
-+
-+ g_return_val_if_fail (family != NULL, NULL);
-+ g_return_val_if_fail (m_scaled_font_table != NULL, NULL);
-+
-+ if (m_color_supported) {
-+ font_name = g_strdup_printf ("%s %u:color=%s",
-+ family, size,
-+ has_color ? "TRUE" : "FALSE");
-+ } else {
-+ font_name = g_strdup_printf ("%s %u", family, size);
-+ }
-+ scaled_font = g_hash_table_lookup (m_scaled_font_table, font_name);
-+ if (scaled_font != NULL) {
-+ g_free (font_name);
-+ return scaled_font;
-+ }
-+ pattern = FcPatternCreate ();
-+ FcPatternAddString (pattern, FC_FAMILY, (FcChar8*) family);
-+ FcPatternAddDouble (pattern, FC_SIZE, (double) size);
-+/* FC_VERSION is for the build check of FC_COLOR and m_color_supported is
-+ * for the runtime check.
-+ */
-+#if FC_VERSION >= 21205
-+ if (m_color_supported)
-+ FcPatternAddBool (pattern, FC_COLOR, has_color);
-+#endif
-+ FcPatternAddDouble (pattern, FC_DPI, 96);
-+ FcConfigSubstitute(NULL, pattern, FcMatchPattern);
-+ font_options = cairo_font_options_create ();
-+ cairo_ft_font_options_substitute (font_options, pattern);
-+ FcDefaultSubstitute (pattern);
-+ resolved = FcFontMatch (NULL, pattern, &result);
-+ FcPatternDestroy (pattern);
-+ FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size);
-+ if (pixel_size == 0.)
-+ g_warning ("Failed to scaled the font: %s %u", family, size);
-+ cairo_face = cairo_ft_font_face_create_for_pattern (resolved);
-+ FcMatrixInit (&fc_matrix);
-+ for (i = 0;
-+ FcPatternGetMatrix (resolved, FC_MATRIX, i, &fc_matrix_val)
-+ == FcResultMatch;
-+ i++) {
-+ FcMatrixMultiply (&fc_matrix, &fc_matrix, fc_matrix_val);
-+ }
-+ FcPatternDestroy (resolved);
-+ cairo_matrix_init (&font_matrix,
-+ fc_matrix.xx, -fc_matrix.yx,
-+ -fc_matrix.xy, fc_matrix.yy,
-+ 0., 0.);
-+ if (pixel_size != 0.)
-+ cairo_matrix_scale (&font_matrix, pixel_size, pixel_size);
-+ cairo_matrix_init_identity (&ctm);
-+ scaled_font = cairo_scaled_font_create (cairo_face,
-+ &font_matrix, &ctm,
-+ font_options);
-+ cairo_font_face_destroy (cairo_face);
-+ if (font_name)
-+ g_hash_table_insert(m_scaled_font_table, font_name, scaled_font);
-+
-+ return scaled_font;
-+}
-+
-+static hb_font_t *
-+ibus_fontset_hb_font_new_with_font_path (const gchar *font_path)
-+{
-+ hb_font_t *hb_font;
-+ GError *error = NULL;
-+ GMappedFile *mf;
-+ char *font_data = NULL;
-+ gsize len;
-+ hb_blob_t *hb_blob;
-+ hb_face_t *hb_face;
-+
-+ g_return_val_if_fail (font_path != NULL, NULL);
-+ g_return_val_if_fail (m_hb_font_table != NULL, NULL);
-+
-+ hb_font = g_hash_table_lookup (m_hb_font_table, font_path);
-+ if (hb_font != NULL)
-+ return hb_font;
-+
-+ mf = g_mapped_file_new (font_path, FALSE, &error);
-+ if (mf == NULL) {
-+ g_warning ("Not found font %s", font_path);
-+ return NULL;
-+ }
-+ font_data = g_mapped_file_get_contents (mf);
-+ len = g_mapped_file_get_length (mf);
-+ if (len == 0) {
-+ g_warning ("zero size font %s", font_path);
-+ g_mapped_file_unref (mf);
-+ return NULL;
-+ }
-+ hb_blob = hb_blob_create (font_data, len,
-+ HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE,
-+ mf, (hb_destroy_func_t)g_mapped_file_unref);
-+ hb_face = hb_face_create (hb_blob, 0);
-+ hb_blob_destroy (hb_blob);
-+ hb_font = hb_font_create (hb_face);
-+ unsigned int upem = hb_face_get_upem (hb_face);
-+ hb_font_set_scale (hb_font, upem, upem);
-+ hb_face_destroy (hb_face);
-+ hb_ot_font_set_funcs (hb_font);
-+ g_hash_table_insert (m_hb_font_table, g_strdup (font_path), hb_font);
-+
-+ return hb_font;
-+}
-+
-+static void
-+get_font_extents_with_scaled_font (cairo_scaled_font_t *scaled_font,
-+ PangoRectangle *font_rect)
-+{
-+ cairo_font_extents_t font_extents;
-+
-+ g_assert (scaled_font != NULL && font_rect != NULL);
-+
-+ cairo_scaled_font_extents (scaled_font, &font_extents);
-+ font_rect->x = 0;
-+ font_rect->y = - pango_units_from_double (font_extents.ascent);
-+ font_rect->width = 0;
-+ font_rect->height = pango_units_from_double (
-+ font_extents.ascent + font_extents.descent);
-+}
-+
-+static void
-+get_glyph_extents_with_scaled_hb_font (const gchar *str,
-+ cairo_scaled_font_t *scaled_font,
-+ hb_font_t *hb_font,
-+ PangoRectangle *font_rect,
-+ IBusCairoLine **cairo_lines,
-+ FcChar8 *fallback_family)
-+{
-+ gboolean has_unknown_glyph = FALSE;
-+ hb_buffer_t *hb_buffer;
-+ unsigned int len, n, i;
-+ hb_glyph_info_t *info;
-+ hb_glyph_position_t *pos;
-+ double x;
-+ cairo_glyph_t *glyph;
-+ cairo_text_extents_t text_extents = { 0, };
-+
-+ g_return_if_fail (str != NULL);
-+
-+ hb_buffer = hb_buffer_create ();
-+ hb_buffer_add_utf8 (hb_buffer, str, -1, 0, -1);
-+ hb_buffer_guess_segment_properties (hb_buffer);
-+ for (n = 0; *cairo_lines && (*cairo_lines)[n].scaled_font; n++);
-+ if (n == 0)
-+ *cairo_lines = g_new0 (IBusCairoLine, 2);
-+ else
-+ *cairo_lines = g_renew (IBusCairoLine, *cairo_lines, n + 2);
-+ (*cairo_lines)[n + 1].scaled_font = NULL;
-+ (*cairo_lines)[n + 1].num_glyphs = 0;
-+ (*cairo_lines)[n + 1].glyphs = NULL;
-+ hb_shape (hb_font, hb_buffer, NULL, 0);
-+ len = hb_buffer_get_length (hb_buffer);
-+ info = hb_buffer_get_glyph_infos (hb_buffer, NULL);
-+ pos = hb_buffer_get_glyph_positions (hb_buffer, NULL);
-+ (*cairo_lines)[n].scaled_font = scaled_font;
-+ (*cairo_lines)[n].num_glyphs = len;
-+ (*cairo_lines)[n].glyphs = (IBusGlyph*) cairo_glyph_allocate (len + 1);
-+ x = 0.;
-+ for (i = 0; i < len; i++) {
-+ hb_codepoint_t c = info[i].codepoint;
-+ if (c) {
-+ (*cairo_lines)[n].glyphs[i].index = info[i].codepoint;
-+ (*cairo_lines)[n].glyphs[i].x = x;
-+ (*cairo_lines)[n].glyphs[i].y = -font_rect->y / PANGO_SCALE;
-+ glyph = (cairo_glyph_t *) &((*cairo_lines)[n].glyphs[i]);
-+ cairo_scaled_font_glyph_extents (scaled_font, glyph,
-+ 1, &text_extents);
-+ x += text_extents.width;
-+ } else {
-+ has_unknown_glyph = TRUE;
-+ c = g_utf8_get_char (str);
-+ (*cairo_lines)[n].glyphs[i].index = PANGO_GET_UNKNOWN_GLYPH (c);
-+ (*cairo_lines)[n].glyphs[i].x = x;
-+ (*cairo_lines)[n].glyphs[i].y = -font_rect->y / PANGO_SCALE;
-+ glyph = (cairo_glyph_t *) &((*cairo_lines)[n].glyphs[i]);
-+ cairo_scaled_font_glyph_extents (scaled_font, glyph,
-+ 1, &text_extents);
-+ x += 10;
-+ }
-+ }
-+ (*cairo_lines)[n].glyphs[i].index = -1;
-+ (*cairo_lines)[n].glyphs[i].x = 0;
-+ (*cairo_lines)[n].glyphs[i].y = 0;
-+ glyph = (cairo_glyph_t *) (*cairo_lines)[n].glyphs;
-+ cairo_scaled_font_glyph_extents (scaled_font, glyph,
-+ len, &text_extents);
-+ if (text_extents.width) {
-+ font_rect->width = pango_units_from_double (text_extents.width);
-+ } else {
-+ font_rect->width = font_rect->height;
-+ }
-+ if (has_unknown_glyph && fallback_family != NULL) {
-+ cairo_scaled_font_t *unknown_font;
-+ unknown_font = ibus_fontset_cairo_scaled_font_new_with_font (
-+ (const gchar *) fallback_family,
-+ UNKNOWN_FONT_SIZE,
-+ FALSE);
-+ (*cairo_lines)[n].scaled_font = unknown_font;
-+ }
-+ hb_buffer_destroy (hb_buffer);
-+}
-+
-+static void
-+get_string_extents_with_font (const gchar *str,
-+ FontPerChar *buff,
-+ cairo_rectangle_int_t *rect,
-+ IBusCairoLine **cairo_lines)
-+{
-+ FcChar8 *family = NULL;
-+ FcChar8 *font_path = NULL;
-+ gboolean has_color = TRUE;
-+ guint size = 0;
-+ cairo_scaled_font_t *scaled_font = NULL;
-+ PangoRectangle font_rect = { 0, };
-+ hb_font_t *hb_font;
-+
-+ g_return_if_fail (str != NULL);
-+ g_return_if_fail (buff != NULL && buff->fcfont != NULL);
-+
-+ FcPatternGetString (buff->fcfont, FC_FAMILY, 0, &family);
-+ g_return_if_fail (family != NULL);
-+#if FC_VERSION >= 21205
-+ if (m_color_supported)
-+ FcPatternGetBool (buff->fcfont, FC_COLOR, 0, &has_color);
-+#endif
-+ size = m_size;
-+ if (size == 0) {
-+ g_warning ("Font size is not right for font %s.", family);
-+ size = 14;
-+ }
-+ scaled_font = ibus_fontset_cairo_scaled_font_new_with_font (
-+ (const gchar *) family,
-+ size,
-+ has_color);
-+ g_return_if_fail (scaled_font != NULL);
-+ get_font_extents_with_scaled_font (scaled_font, &font_rect);
-+
-+ FcPatternGetString (buff->fcfont, FC_FILE, 0, &font_path);
-+ g_return_if_fail (font_path != NULL);
-+ hb_font = ibus_fontset_hb_font_new_with_font_path (
-+ (const gchar *) font_path);
-+ if (hb_font == NULL)
-+ return;
-+ get_glyph_extents_with_scaled_hb_font (str,
-+ scaled_font,
-+ hb_font,
-+ &font_rect,
-+ cairo_lines,
-+ family);
-+ rect->width += font_rect.width / PANGO_SCALE;
-+ rect->height += font_rect.height / PANGO_SCALE;
-+}
-+
-+static FT_Face
-+ibus_fontset_get_ftface_from_fcfont (IBusFontSet *fontset,
-+ FcPattern *fcfont)
-+{
-+ FcChar8 *font_file = NULL;
-+ FT_Face ft_face;
-+ guint size = ibus_fontset_get_size (fontset);
-+
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), NULL);
-+ g_return_val_if_fail (fcfont != NULL, NULL);
-+
-+ size = ibus_fontset_get_size (fontset);
-+ FcPatternGetString (fcfont, FC_FILE, 0, &font_file);
-+ FT_New_Face (m_ftlibrary, (const gchar *) font_file, 0, &ft_face);
-+ FT_Set_Pixel_Sizes (ft_face, size, size);
-+ return ft_face;
-+}
-+
-+static void
-+_cairo_show_unknown_glyphs (cairo_t *cr,
-+ const cairo_glyph_t *glyphs,
-+ guint num_glyphs,
-+ guint width,
-+ guint height)
-+{
-+ gunichar ch;
-+ gboolean invalid_input;
-+ int rows = 2;
-+ int cols;
-+ int row, col;
-+ char buf[7];
-+ double cx = 0.;
-+ double cy;
-+ const double box_descent = 3.;
-+ double x0;
-+ double y0;
-+ const double digit_width = 5.;
-+ const double digit_height= 6.;
-+ char hexbox_string[2] = {0, 0};
-+
-+ g_assert (glyphs != NULL);
-+ g_assert (num_glyphs > 0);
-+
-+ ch = glyphs[0].index & ~PANGO_GLYPH_UNKNOWN_FLAG;
-+ invalid_input = G_UNLIKELY (glyphs[0].index == PANGO_GLYPH_INVALID_INPUT ||
-+ ch > 0x10FFFF);
-+ if (G_UNLIKELY (invalid_input)) {
-+ g_warning ("Unsupported U+%06X", ch);
-+ return;
-+ }
-+
-+ cairo_save (cr);
-+
-+ cols = (ch > 0xffff ? 6 : 4) / rows;
-+ g_snprintf (buf, sizeof(buf), (ch > 0xffff) ? "%06X" : "%04X", ch);
-+ cy = (double) height;
-+ x0 = cx + box_descent + XPAD / 2;
-+ y0 = cy - box_descent - YPAD / 2;
-+
-+ for (row = 0; row < rows; row++) {
-+ double y = y0 - (rows - 1 - row) * (digit_height + YPAD);
-+ for (col = 0; col < cols; col++) {
-+ double x = x0 + col * (digit_width + XPAD);
-+ cairo_move_to (cr, x, y);
-+ hexbox_string[0] = buf[row * cols + col];
-+ cairo_show_text (cr, hexbox_string);
-+ }
-+ }
-+ cairo_move_to (cr, XPAD, YPAD);
-+ cairo_line_to (cr, width - XPAD, YPAD);
-+ cairo_line_to (cr, width - XPAD,
-+ height - YPAD);
-+ cairo_line_to (cr, XPAD, height - YPAD);
-+ cairo_line_to (cr, XPAD, YPAD);
-+ cairo_set_line_width (cr, 1.);
-+ cairo_stroke (cr);
-+
-+ cairo_restore (cr);
-+}
-+
-+static void
-+ibus_fcfontset_destroy_ex (FcFontSetEx *fcfontset_ex)
-+{
-+ FcFontSet *fcfontset = NULL;
-+ int i;
-+
-+ g_return_if_fail (fcfontset_ex != NULL);
-+
-+ for (i = 0; i < fcfontset_ex->nfont; i++)
-+ FT_Done_Face (fcfontset_ex->ft_faces[i]);
-+ fcfontset = FcFontSetCreate ();
-+ fcfontset->nfont = fcfontset_ex->nfont;
-+ fcfontset->sfont = fcfontset_ex->sfont;
-+ fcfontset->fonts = fcfontset_ex->fonts;
-+ FcFontSetDestroy (fcfontset);
-+ g_free (fcfontset_ex->ft_faces);
-+ g_free (fcfontset_ex);
-+}
-+
-+IBusCairoLine *
-+ibus_cairo_line_copy (IBusCairoLine *cairo_lines)
-+{
-+ IBusCairoLine *ret;
-+ guint n, i, j, num_glyphs;
-+ if (!cairo_lines)
-+ return NULL;
-+
-+ for (n = 0; cairo_lines[n].scaled_font; n++);
-+ ret = g_new0 (IBusCairoLine, n + 1);
-+ for (i = 0; i < n; i++) {
-+ ret[i].scaled_font = cairo_lines[i].scaled_font;
-+ num_glyphs = cairo_lines[i].num_glyphs;
-+ ret[i].num_glyphs = num_glyphs;
-+ ret[i].glyphs = (IBusGlyph *) cairo_glyph_allocate (num_glyphs + 1);
-+ for (j = 0; j < num_glyphs; j++) {
-+ ret[i].glyphs[j] = cairo_lines[i].glyphs[j];
-+ }
-+ ret[i].glyphs[j].index = -1;
-+ ret[i].glyphs[j].x = 0;
-+ ret[i].glyphs[j].y = 0;
-+ }
-+ ret[i].scaled_font = NULL;
-+ ret[i].num_glyphs = 0;
-+ ret[i].glyphs = NULL;
-+ return ret;
-+}
-+
-+void
-+ibus_cairo_line_free (IBusCairoLine *cairo_lines)
-+{
-+ guint i;
-+ if (!cairo_lines)
-+ return;
-+ for (i = 0; cairo_lines[i].scaled_font; i++) {
-+ g_free (cairo_lines[i].glyphs);
-+ }
-+ g_free (cairo_lines);
-+}
-+
-+IBusRequisitionEx *
-+ibus_requisition_ex_copy (IBusRequisitionEx *req)
-+{
-+ IBusRequisitionEx *ret;
-+ if (!req)
-+ return NULL;
-+ ret = g_new0 (IBusRequisitionEx, 1);
-+ ret->width = req->width;
-+ ret->height = req->height;
-+ ret->cairo_lines = ibus_cairo_line_copy (req->cairo_lines);
-+ return ret;
-+}
-+
-+void
-+ibus_requisition_ex_free (IBusRequisitionEx *req)
-+{
-+ if (!req)
-+ return;
-+ g_clear_pointer (&req->cairo_lines, ibus_cairo_line_free);
-+ g_free (req);
-+}
-+
-+IBusFontSet *
-+ibus_fontset_new (const gchar *first_property_name, ...)
-+{
-+ va_list var_args;
-+ IBusFontSet *fontset;
-+
-+ g_assert (first_property_name);
-+
-+ va_start (var_args, first_property_name);
-+ fontset = (IBusFontSet *)g_object_new_valist (IBUS_TYPE_FONTSET,
-+ first_property_name,
-+ var_args);
-+ va_end (var_args);
-+ g_assert (fontset->priv->family);
-+ g_assert (fontset->priv->language);
-+ return fontset;
-+}
-+
-+IBusFontSet *
-+ibus_fontset_new_with_font (const gchar *family,
-+ guint size,
-+ const gchar *language)
-+{
-+ return ibus_fontset_new ("family", family,
-+ "size", size,
-+ "language", language,
-+ NULL);
-+}
-+
-+void
-+ibus_fontset_exit ()
-+{
-+ g_clear_pointer (&m_ftlibrary, FT_Done_FreeType);
-+}
-+
-+const gchar *
-+ibus_fontset_get_family (IBusFontSet *fontset)
-+{
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), NULL);
-+ return fontset->priv->family;
-+}
-+
-+void
-+ibus_fontset_set_family (IBusFontSet *fontset,
-+ const gchar *family)
-+{
-+ g_return_if_fail (IBUS_IS_FONTSET (fontset));
-+ g_free (fontset->priv->family);
-+ fontset->priv->family = g_strdup (family);
-+}
-+
-+guint
-+ibus_fontset_get_size (IBusFontSet *fontset)
-+{
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), 0);
-+ return fontset->priv->size;
-+}
-+
-+void
-+ibus_fontset_set_size (IBusFontSet *fontset,
-+ guint size)
-+{
-+ g_return_if_fail (IBUS_IS_FONTSET (fontset));
-+ fontset->priv->size = size;
-+}
-+
-+const gchar *
-+ibus_fontset_get_language (IBusFontSet *fontset)
-+{
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), NULL);
-+ return fontset->priv->language;
-+}
-+
-+void
-+ibus_fontset_set_language (IBusFontSet *fontset,
-+ const gchar *language)
-+{
-+ g_return_if_fail (IBUS_IS_FONTSET (fontset));
-+ g_free (fontset->priv->language);
-+ fontset->priv->language = g_strdup (language);
-+}
-+
-+gboolean
-+ibus_fontset_update_fcfontset (IBusFontSet *fontset)
-+{
-+ FcPattern *pattern;
-+ const gchar *family;
-+ guint size;
-+ const gchar *language;
-+ gboolean update_fontset = FALSE;
-+ FcFontSet *fcfontset = NULL;
-+ FcResult result;
-+
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), FALSE);
-+
-+ pattern = FcPatternCreate ();
-+ family = fontset->priv->family;
-+ size = fontset->priv->size;
-+ language = fontset->priv->language;
-+
-+ if (g_strcmp0 (m_family, family)) {
-+ g_free (m_family);
-+ m_family = g_strdup (family);
-+ update_fontset = TRUE;
-+ }
-+ if (m_size != size) {
-+ m_size = size;
-+ update_fontset = TRUE;
-+ }
-+ if (g_strcmp0 (m_language, language)) {
-+ g_free (m_language);
-+ m_language = g_strdup (language);
-+ update_fontset = TRUE;
-+ }
-+ if (!update_fontset && m_fcfontset != NULL)
-+ return FALSE;
-+
-+ if (m_font_index_per_char_table)
-+ g_hash_table_destroy (m_font_index_per_char_table);
-+ if (m_fcfontset)
-+ g_clear_pointer (&m_fcfontset, ibus_fcfontset_destroy_ex);
-+
-+ m_font_index_per_char_table = g_hash_table_new (g_direct_hash,
-+ g_direct_equal);
-+ if (g_strcmp0 (family, ""))
-+ FcPatternAddString (pattern, FC_FAMILY, (const FcChar8*) family);
-+ if (size > 0)
-+ FcPatternAddDouble (pattern, FC_SIZE, (double) size);
-+ if (g_strcmp0 (language, ""))
-+ FcPatternAddString (pattern, FC_LANG, (const FcChar8*) language);
-+ FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_NORMAL);
-+ FcPatternAddInteger (pattern, FC_WIDTH, FC_WIDTH_NORMAL);
-+ FcPatternAddInteger (pattern, FC_DPI, 96);
-+#if FC_VERSION >= 21205
-+ if (m_color_supported &&
-+ (!g_ascii_strncasecmp (family, MONOSPACE, strlen (MONOSPACE)) ||
-+ !g_ascii_strncasecmp (family, SERIF, strlen (SERIF)) ||
-+ !g_ascii_strncasecmp (family, SANS, strlen (SANS)))) {
-+ FcPatternAddBool (pattern, FC_COLOR, TRUE);
-+ }
-+#endif
-+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
-+ FcConfigSubstitute (NULL, pattern, FcMatchFont);
-+ FcDefaultSubstitute (pattern);
-+ fcfontset = FcFontSort (NULL, pattern, FcTrue, NULL, &result);
-+ FcPatternDestroy (pattern);
-+ if (result == FcResultNoMatch || fcfontset->nfont == 0) {
-+ g_warning ("No FcFontSet for %s", family ? family : "(null)");
-+ return FALSE;
-+ }
-+ m_fcfontset = g_new0 (FcFontSetEx, 1);
-+ m_fcfontset->nfont = fcfontset->nfont;
-+ m_fcfontset->sfont = fcfontset->sfont;
-+ m_fcfontset->fonts = fcfontset->fonts;
-+ m_fcfontset->ft_faces = g_new0 (FT_Face, fcfontset->nfont);
-+ fcfontset->nfont = 0;
-+ fcfontset->sfont = 0;
-+ fcfontset->fonts = NULL;
-+ FcFontSetDestroy (fcfontset);
-+ return TRUE;
-+}
-+
-+void
-+ibus_fontset_unref (IBusFontSet *fontset)
-+{
-+ g_object_unref (fontset);
-+}
-+
-+IBusRequisitionEx *
-+ibus_fontset_get_preferred_size_hb (IBusFontSet *fontset,
-+ const gchar *text,
-+ cairo_rectangle_int_t *widest)
-+{
-+ gchar *copied_text;
-+ gchar *p;
-+ FontPerChar *buff;
-+ IBusCairoLine *cairo_lines = NULL;
-+ IBusRequisitionEx *req = NULL;
-+ GString *str = NULL;
-+ int text_length;
-+ int i, n = 0;
-+
-+ g_return_val_if_fail (IBUS_IS_FONTSET (fontset), NULL);
-+ g_return_val_if_fail (m_fcfontset != NULL, NULL);
-+
-+ copied_text = g_strdup (text);
-+ text_length = g_utf8_strlen (text, -1);
-+ buff = g_slice_alloc0 (sizeof (FontPerChar) * text_length);
-+ str = g_string_new (NULL);
-+
-+ for (p = copied_text; *p != '\0'; p = g_utf8_next_char (p)) {
-+ gunichar c = g_utf8_get_char (p);
-+ gboolean has_glyphs = FALSE;
-+ buff[n].ch = c;
-+ if ((c == 0xfe0eu || c == 0xfe0fu) && n > 0) {
-+ buff[n].fcfont = buff[n-1].fcfont;
-+ ++n;
-+ continue;
-+ }
-+ i = GPOINTER_TO_INT (g_hash_table_lookup (m_font_index_per_char_table,
-+ GINT_TO_POINTER (c)));
-+ if (i > 0) {
-+ i--;
-+ if (i >= m_fcfontset->nfont) {
-+ g_warning ("i:%d >= m_fcfontset->nfont:%d",
-+ i, m_fcfontset->nfont);
-+ } else {
-+ buff[n].fcfont = m_fcfontset->fonts[i];
-+ has_glyphs = TRUE;
-+ }
-+ }
-+ for (; i < m_fcfontset->nfont; i++) {
-+ if (!has_glyphs && g_unichar_iscntrl (c) && !g_unichar_isspace (c))
-+ break;
-+ FT_Face ft_face = m_fcfontset->ft_faces[i];
-+ if (!has_glyphs && ft_face == 0) {
-+ ft_face = ibus_fontset_get_ftface_from_fcfont (
-+ fontset,
-+ m_fcfontset->fonts[i]);
-+ m_fcfontset->ft_faces[i] = ft_face;
-+ }
-+ if (has_glyphs || FT_Get_Char_Index (ft_face, c) != 0) {
-+ FcChar8 *font_file = NULL;
-+ FcPatternGetString (m_fcfontset->fonts[i], FC_FILE, 0, &font_file);
-+ buff[n].fcfont = m_fcfontset->fonts[i];
-+ if (!has_glyphs) {
-+ g_hash_table_insert (m_font_index_per_char_table,
-+ GINT_TO_POINTER (c),
-+ GINT_TO_POINTER (i + 1));
-+ }
-+ if (n > 0 && buff[n - 1].fcfont != buff[n].fcfont) {
-+ get_string_extents_with_font (str->str,
-+ &buff[n - 1],
-+ widest,
-+ &cairo_lines);
-+ g_string_free (str, TRUE);
-+ str = g_string_new (NULL);
-+ g_string_append_unichar (str, c);
-+ } else {
-+ g_string_append_unichar (str, c);
-+ }
-+ ++n;
-+ has_glyphs = TRUE;
-+ break;
-+ }
-+ }
-+ if (!has_glyphs) {
-+ if (n > 0) {
-+ buff[n].fcfont = buff[n - 1].fcfont;
-+ } else {
-+ /* Search a font for non-glyph char to draw the code points
-+ * likes Pango.
-+ */
-+ for (i = 0; i < m_fcfontset->nfont; i++) {
-+ FT_Face ft_face = m_fcfontset->ft_faces[i];
-+ if (ft_face == 0) {
-+ ft_face = ibus_fontset_get_ftface_from_fcfont (
-+ fontset,
-+ m_fcfontset->fonts[i]);
-+ m_fcfontset->ft_faces[i] = ft_face;
-+ }
-+ /* Check alphabets instead of space or digits
-+ * because 'Noto Emoji Color' font's digits are
-+ * white color and cannot change the font color.
-+ * the font does not have alphabets.
-+ */
-+ if (FT_Get_Char_Index (ft_face, 'A') != 0) {
-+ FcChar8 *font_file = NULL;
-+ FcPatternGetString (m_fcfontset->fonts[i], FC_FILE, 0, &font_file);
-+ buff[n].fcfont = m_fcfontset->fonts[i];
-+ g_hash_table_insert (m_font_index_per_char_table,
-+ GINT_TO_POINTER (c),
-+ GINT_TO_POINTER (i + 1));
-+ has_glyphs = TRUE;
-+ break;
-+ }
-+ }
-+ if (!has_glyphs) {
-+ buff[n].fcfont = m_fcfontset->fonts[0];
-+ g_hash_table_insert (m_font_index_per_char_table,
-+ GINT_TO_POINTER (c),
-+ GINT_TO_POINTER (1));
-+ g_warning ("Not found fonts for unicode %04X at %d in %s",
-+ c, n, text);
-+ }
-+ }
-+ n++;
-+ g_string_append_unichar (str, c);
-+ }
-+ }
-+ if (str->str) {
-+ get_string_extents_with_font (str->str,
-+ &buff[n - 1],
-+ widest,
-+ &cairo_lines);
-+ g_string_free (str, TRUE);
-+ }
-+ g_slice_free1 (sizeof (FontPerChar) * text_length, buff);
-+ g_free (copied_text);
-+ widest->width += XPAD * 2;
-+ widest->height += YPAD * 2;
-+ req = g_new0 (IBusRequisitionEx, 1);
-+ req->width = widest->width;
-+ req->height = widest->height;
-+ req->cairo_lines = cairo_lines;
-+ return req;
-+}
-+
-+void
-+ibus_fontset_draw_cairo_with_requisition_ex (IBusFontSet *fontset,
-+ cairo_t *cr,
-+ IBusRequisitionEx *ex)
-+{
-+ IBusCairoLine *cairo_lines;
-+ int i;
-+
-+ g_return_if_fail (IBUS_IS_FONTSET (fontset));
-+ g_return_if_fail (cr != NULL);
-+ g_return_if_fail (ex != NULL);
-+
-+ cairo_lines = ex->cairo_lines;
-+ g_return_if_fail (cairo_lines != NULL);
-+
-+ for (i = 0; cairo_lines[i].scaled_font; i++) {
-+ const cairo_glyph_t *glyphs = (cairo_glyph_t *) cairo_lines[i].glyphs;
-+ guint num_glyphs = cairo_lines[i].num_glyphs;
-+
-+ cairo_ft_scaled_font_lock_face (cairo_lines[i].scaled_font);
-+ cairo_set_scaled_font (cr, cairo_lines[i].scaled_font);
-+ if (num_glyphs > 0 && glyphs[0].index & PANGO_GLYPH_UNKNOWN_FLAG) {
-+ _cairo_show_unknown_glyphs (cr, glyphs, num_glyphs,
-+ ex->width, ex->height);
-+ } else {
-+ cairo_show_glyphs (cr, glyphs, num_glyphs);
-+ }
-+ cairo_ft_scaled_font_unlock_face (cairo_lines[i].scaled_font);
-+ }
-+}
-diff --git a/ui/gtk3/ibusfontset.h b/ui/gtk3/ibusfontset.h
-new file mode 100644
-index 00000000..efcaa286
---- /dev/null
-+++ b/ui/gtk3/ibusfontset.h
-@@ -0,0 +1,302 @@
-+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
-+/* vim:set et sts=4: */
-+/* ibus - The Input Bus
-+ * Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
-+ * Copyright (C) 2017 Red Hat, Inc.
-+ *
-+ * 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.1 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, write to the Free Software
-+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
-+ * USA
-+ */
-+
-+#ifndef __IBUS_HARFBUZZ_H_
-+#define __IBUS_HARFBUZZ_H_
-+
-+/**
-+ * SECTION: ibusfontset
-+ * @short_description: Object for HarfBuzz and Fontconfig.
-+ * @title: IBusFontSet
-+ * @stability: Unstable
-+ *
-+ * IBusFontSet offers FcFontSet, glyph info with HarfBuzz and rendering
-+ * on Cairo context.
-+ * Current Pango changes fonts by emoji variants and draws the separated
-+ * glyphs [1] but actually the emoji characters with variants can be drawn
-+ * as one glyph so this class manages Fontconfig fontsets to select a font,
-+ * HarfBuzz to get glyphs for emoji variants, Cairo to draw glyphs.
-+ *
-+ * [1]: https://bugzilla.gnome.org/show_bug.cgi?id=780669
-+ * https://bugzilla.gnome.org/show_bug.cgi?id=781123
-+ */
-+
-+#include <ibus.h>
-+#include <cairo.h>
-+
-+#define IBUS_TYPE_CAIRO_LINE (ibus_cairo_line_get_type ())
-+#define IBUS_TYPE_REQUISITION_EX (ibus_requisition_ex_get_type ())
-+#define IBUS_TYPE_FONTSET (ibus_fontset_get_type ())
-+#define IBUS_FONTSET(obj) (G_TYPE_CHECK_INSTANCE_CAST (\
-+ (obj), \
-+ IBUS_TYPE_FONTSET, \
-+ IBusFontSet))
-+#define IBUS_FONTSET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST (\
-+ (klass), \
-+ IBUS_TYPE_FONTSET, \
-+ IBusFontSetClass))
-+#define IBUS_IS_FONTSET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (\
-+ (obj), \
-+ IBUS_TYPE_FONTSET))
-+#define IBUS_IS_FONTSET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE (\
-+ (klass), \
-+ IBUS_TYPE_FONTSET))
-+#define IBUS_FONTSET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS (\
-+ (obj), \
-+ IBUS_TYPE_FONTSET, \
-+ IBusFontSetClass))
-+
-+G_BEGIN_DECLS
-+
-+typedef struct _IBusGlyph IBusGlyph;
-+typedef struct _IBusCairoLine IBusCairoLine;
-+typedef struct _IBusRequisitionEx IBusRequisitionEx;
-+typedef struct _IBusFontSet IBusFontSet;
-+typedef struct _IBusFontSetPrivate IBusFontSetPrivate;
-+typedef struct _IBusFontSetClass IBusFontSetClass;
-+
-+struct _IBusGlyph {
-+ unsigned long index;
-+ double x;
-+ double y;
-+};
-+
-+struct _IBusCairoLine {
-+ IBusGlyph *glyphs;
-+ guint num_glyphs;
-+ cairo_scaled_font_t *scaled_font;
-+ gpointer pdummy[5];
-+};
-+
-+struct _IBusRequisitionEx {
-+ guint width;
-+ guint height;
-+ IBusCairoLine *cairo_lines;
-+ gpointer pdummy[5];
-+};
-+
-+struct _IBusFontSet {
-+ IBusObject parent_instance;
-+ IBusFontSetPrivate *priv;
-+};
-+
-+struct _IBusFontSetClass {
-+ IBusObjectClass parent_class;
-+ /* signals */
-+ /*< private >*/
-+ /* padding */
-+ gpointer pdummy[10];
-+};
-+
-+GType ibus_cairo_line_get_type (void) G_GNUC_CONST;
-+
-+/**
-+ * ibus_cairo_line_copy:
-+ * @cairo_lines: #IBusCairoLine
-+ *
-+ * Creates a copy of @cairo_liens, which should be freed with
-+ * ibus_cairo_line_free(). Primarily used by language bindings,
-+ * not that useful otherwise (since @req can just be copied
-+ * by assignment in C).
-+ *
-+ * Returns: the newly allocated #IBusCairoLine, which should
-+ * be freed with ibus_cairo_line_free(), or %NULL
-+ * if @cairo_lines was %NULL.
-+ **/
-+IBusCairoLine * ibus_cairo_line_copy (IBusCairoLine *cairo_lines);
-+
-+/**
-+ * ibus_cairo_line_free:
-+ * @cairo_lines: #IBusCairoLine
-+ *
-+ * Free an #IBusCairoLine.
-+ */
-+void ibus_cairo_line_free (IBusCairoLine *cairo_lines);
-+
-+
-+GType ibus_requisition_ex_get_type (void) G_GNUC_CONST;
-+
-+/**
-+ * ibus_requisition_ex_copy:
-+ * @req: #IBusRequisitionEx
-+ *
-+ * Creates a copy of @req, which should be freed with
-+ * ibus_requisition_ex_free(). Primarily used by language bindings,
-+ * not that useful otherwise (since @req can just be copied
-+ * by assignment in C).
-+ *
-+ * Returns: the newly allocated #IBusRequisitionEx, which should
-+ * be freed with ibus_requisition_ex_free(), or %NULL
-+ * if @req was %NULL.
-+ **/
-+IBusRequisitionEx *
-+ ibus_requisition_ex_copy (IBusRequisitionEx *req);
-+
-+/**
-+ * ibus_requisition_ex_free:
-+ * @req: #IBusRequisitionEx
-+ *
-+ * Free an #IBusRequisitionEx.
-+ */
-+void ibus_requisition_ex_free (IBusRequisitionEx *req);
-+
-+
-+GType ibus_fontset_get_type (void);
-+
-+/**
-+ * ibus_fontset_new:
-+ * @first_property_name:
-+ *
-+ * Creates a new #IBusFcFontSet.
-+ *
-+ * Returns: (transfer full): A newly allocated #IBusFontSet and includes
-+ * #FcFontSet internally. E.g. ibus_fontset_new ("family",
-+ * "Noto Emoji Color", "size", 16, "language", "ja-jp");
-+ */
-+IBusFontSet * ibus_fontset_new (const gchar
-+ *first_property_name,
-+ ...);
-+
-+/**
-+ * ibus_fontset_new_with_font:
-+ * @family: font family
-+ * @size: font size
-+ * @language: font language
-+ *
-+ * Creates a new #IBusFcFontSet.
-+ *
-+ * Returns: (transfer full): A newly allocated #IBusFcFontSet and includes
-+ * #FcFontSet internally.
-+ */
-+IBusFontSet * ibus_fontset_new_with_font (const gchar *family,
-+ guint size,
-+ const gchar *language);
-+/**
-+ * ibus_fontset_get_family:
-+ * @fontset: #IBusFcFontSet
-+ *
-+ * Return the base font family of #FcFontSet
-+ *
-+ * Returns: Base font family of #FcFontSet
-+ */
-+const gchar * ibus_fontset_get_family (IBusFontSet *fontset);
-+
-+/**
-+ * ibus_fontset_set_family:
-+ * @fontset: #IBusFcFontSet
-+ * @family: base font family for #FcFontSet
-+ *
-+ * Set the base font family for #FcFontSet
-+ */
-+void ibus_fontset_set_family (IBusFontSet *fontset,
-+ const gchar *family);
-+/**
-+ * ibus_fontset_get_size:
-+ * @fontset: #IBusFcFontSet
-+ *
-+ * Return the font size of #FcFontSet
-+ *
-+ * Returns: Font size of #FcFontSet
-+ */
-+guint ibus_fontset_get_size (IBusFontSet *fontset);
-+
-+/**
-+ * ibus_fontset_set_size:
-+ * @fontset: #IBusFcFontSet
-+ * @size: font size for #FcFontSet
-+ *
-+ * Set the font size for #FcFontSet
-+ */
-+void ibus_fontset_set_size (IBusFontSet *fontset,
-+ guint size);
-+/**
-+ * ibus_fontset_get_language:
-+ * @fontset: #IBusFcFontSet
-+ *
-+ * Return the font language of #FcFontSet
-+ *
-+ * Returns: Font language of #FcFontSet
-+ */
-+const gchar * ibus_fontset_get_language (IBusFontSet *fontset);
-+
-+/**
-+ * ibus_fontset_set_language:
-+ * @fontset: #IBusFcFontSet
-+ * @language: font langauge for #FcFontSet
-+ *
-+ * Set the font language for #FcFontSet
-+ */
-+void ibus_fontset_set_language (IBusFontSet *fontset,
-+ const gchar *language);
-+
-+/**
-+ * ibus_fontset_update_fcfontset:
-+ * @fontset: #IBusFcFontSet
-+ *
-+ * Update #FcFontSet from font family, size and langauge of @fontset.
-+ * Returns: %TRUE if #FcFontSet is updated. %FALSE otherwise.
-+ */
-+gboolean ibus_fontset_update_fcfontset (IBusFontSet *fontset);
-+
-+/**
-+ * ibus_fontset_get_preferred_size_hb:
-+ * @fontset: #IBusFcFontSet
-+ * @text: a string to be calculate the preferred rectangle size.
-+ * @widest: (out): #cairo_rectangle_int_t is updated.
-+ *
-+ * Calculate @widest for @text.
-+ *
-+ * Returns: #IBusRequisitionEx which includes the glyphs and coordinates.
-+ */
-+IBusRequisitionEx *
-+ ibus_fontset_get_preferred_size_hb
-+ (IBusFontSet *fontset,
-+ const gchar *text,
-+ cairo_rectangle_int_t
-+ *widest);
-+
-+/**
-+ * ibus_fontset_draw_cairo_lines:
-+ * @fontset: #IBusFcFontSet
-+ * @cr: #cairo_t in #GtkWidget.draw().
-+ * @ex: #IBusRequisitionEx which includes glyph, x, y values, char width
-+ * and height.
-+ *
-+ * Draw glyphs in @ex using cairo @cr.
-+ */
-+void ibus_fontset_draw_cairo_with_requisition_ex
-+ (IBusFontSet *fontset,
-+ cairo_t *cr,
-+ IBusRequisitionEx
-+ *ex);
-+
-+/**
-+ * ibus_fontset_unref:
-+ * @fontset: #IBusFcFontSet
-+ *
-+ * Call g_object_unref().
-+ * FIXME: Seems Vala needs this API.
-+ */
-+void ibus_fontset_unref (IBusFontSet *fontset);
-+
-+G_END_DECLS
-+#endif
---
-2.14.3
-
reply other threads:[~2026-05-31 2:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178019321231.1.13345828956723386725.rpms-ibus-3bca2d162b45@fedoraproject.org \
--to=tfujiwar@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox