LEFT | RIGHT |
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ | 1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ |
2 /* vim:set et sts=4: */ | 2 /* vim:set et sts=4: */ |
3 /* ibus - The Input Bus | 3 /* ibus - The Input Bus |
4 * Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com> | 4 * Copyright (C) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com> |
5 * Copyright (C) 2017 Red Hat, Inc. | 5 * Copyright (C) 2017 Red Hat, Inc. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
(...skipping 17 matching lines...) Expand all Loading... |
28 #include <hb-ot.h> | 28 #include <hb-ot.h> |
29 #include <pango/pango.h> | 29 #include <pango/pango.h> |
30 | 30 |
31 #include "ibusfontset.h" | 31 #include "ibusfontset.h" |
32 | 32 |
33 #define XPAD 2 | 33 #define XPAD 2 |
34 #define YPAD 2 | 34 #define YPAD 2 |
35 #define UNKNOWN_FONT_SIZE 7 | 35 #define UNKNOWN_FONT_SIZE 7 |
36 #define IBUS_FONTSET_GET_PRIVATE(o) \ | 36 #define IBUS_FONTSET_GET_PRIVATE(o) \ |
37 (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FONTSET, IBusFontSetPrivate)) | 37 (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_FONTSET, IBusFontSetPrivate)) |
38 | 38 #define MONOSPACE "monospace" |
39 | 39 #define SERIF "serif" |
| 40 #define SANS "sans" |
| 41 |
| 42 |
| 43 static gboolean m_color_supported; |
40 static FT_Library m_ftlibrary; | 44 static FT_Library m_ftlibrary; |
41 static FcFontSet *m_fcfontset; | 45 static FcFontSet *m_fcfontset; |
42 static gchar *m_family; | 46 static gchar *m_family; |
43 static guint m_size; | 47 static guint m_size; |
44 static gchar *m_language; | 48 static gchar *m_language; |
45 static GHashTable *m_scaled_font_table; | 49 static GHashTable *m_scaled_font_table; |
46 static GHashTable *m_hb_font_table; | 50 static GHashTable *m_hb_font_table; |
47 | 51 |
48 enum { | 52 enum { |
49 PROP_0, | 53 PROP_0, |
(...skipping 21 matching lines...) Expand all Loading... |
71 guint prop_id, | 75 guint prop_id, |
72 const GValue *value, | 76 const GValue *value, |
73 GParamSpec *pspec); | 77 GParamSpec *pspec); |
74 static void ibus_fontset_get_property (IBusFontSet *fontset, | 78 static void ibus_fontset_get_property (IBusFontSet *fontset, |
75 guint prop_id, | 79 guint prop_id, |
76 GValue *value, | 80 GValue *value, |
77 GParamSpec *pspec); | 81 GParamSpec *pspec); |
78 static cairo_scaled_font_t * | 82 static cairo_scaled_font_t * |
79 ibus_fontset_cairo_scaled_font_new_with_font | 83 ibus_fontset_cairo_scaled_font_new_with_font |
80 (const gchar *family, | 84 (const gchar *family, |
81 guint size); | 85 guint size, |
| 86 gboolean has_color); |
82 | 87 |
83 G_DEFINE_BOXED_TYPE (IBusCairoLine, | 88 G_DEFINE_BOXED_TYPE (IBusCairoLine, |
84 ibus_cairo_line, | 89 ibus_cairo_line, |
85 ibus_cairo_line_copy, | 90 ibus_cairo_line_copy, |
86 ibus_cairo_line_free); | 91 ibus_cairo_line_free); |
87 G_DEFINE_BOXED_TYPE (IBusRequisitionEx, | 92 G_DEFINE_BOXED_TYPE (IBusRequisitionEx, |
88 ibus_requisition_ex, | 93 ibus_requisition_ex, |
89 ibus_requisition_ex_copy, | 94 ibus_requisition_ex_copy, |
90 ibus_requisition_ex_free); | 95 ibus_requisition_ex_free); |
91 G_DEFINE_TYPE (IBusFontSet, ibus_fontset, IBUS_TYPE_OBJECT) | 96 G_DEFINE_TYPE (IBusFontSet, ibus_fontset, IBUS_TYPE_OBJECT) |
92 | 97 |
93 static void | 98 static void |
94 ibus_fontset_class_init (IBusFontSetClass *class) | 99 ibus_fontset_class_init (IBusFontSetClass *class) |
95 { | 100 { |
96 GObjectClass *gobject_class = G_OBJECT_CLASS (class); | 101 GObjectClass *gobject_class = G_OBJECT_CLASS (class); |
97 IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); | 102 IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); |
98 cairo_glyph_t dummy; | 103 cairo_glyph_t dummy; |
99 IBusGlyph dummy2; | 104 IBusGlyph dummy2; |
100 | 105 |
| 106 m_color_supported = (FcGetVersion () >= 21205); |
101 gobject_class->constructor = ibus_fontset_constructor; | 107 gobject_class->constructor = ibus_fontset_constructor; |
102 gobject_class->get_property = | 108 gobject_class->get_property = |
103 (GObjectGetPropertyFunc) ibus_fontset_get_property; | 109 (GObjectGetPropertyFunc) ibus_fontset_get_property; |
104 gobject_class->set_property = | 110 gobject_class->set_property = |
105 (GObjectSetPropertyFunc) ibus_fontset_set_property; | 111 (GObjectSetPropertyFunc) ibus_fontset_set_property; |
106 object_class->destroy = (IBusObjectDestroyFunc) ibus_fontset_destroy; | 112 object_class->destroy = (IBusObjectDestroyFunc) ibus_fontset_destroy; |
107 | 113 |
108 /* install properties */ | 114 /* install properties */ |
109 /** | 115 /** |
110 * IBusFontSet:family: | 116 * IBusFontSet:family: |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 | 188 |
183 object = G_OBJECT_CLASS (ibus_fontset_parent_class)->constructor ( | 189 object = G_OBJECT_CLASS (ibus_fontset_parent_class)->constructor ( |
184 type, n ,args); | 190 type, n ,args); |
185 fontset = IBUS_FONTSET (object); | 191 fontset = IBUS_FONTSET (object); |
186 family = ibus_fontset_get_family (fontset); | 192 family = ibus_fontset_get_family (fontset); |
187 size = ibus_fontset_get_size (fontset); | 193 size = ibus_fontset_get_size (fontset); |
188 ibus_fontset_update_fcfontset (fontset); | 194 ibus_fontset_update_fcfontset (fontset); |
189 if (family != NULL && size > 0) { | 195 if (family != NULL && size > 0) { |
190 /* cache the font */ | 196 /* cache the font */ |
191 ibus_fontset_cairo_scaled_font_new_with_font (family, | 197 ibus_fontset_cairo_scaled_font_new_with_font (family, |
192 size); | 198 size, |
| 199 TRUE); |
193 } | 200 } |
194 return object; | 201 return object; |
195 } | 202 } |
196 | 203 |
197 static void | 204 static void |
198 ibus_fontset_destroy (IBusFontSet *fontset) | 205 ibus_fontset_destroy (IBusFontSet *fontset) |
199 { | 206 { |
200 g_clear_pointer (&fontset->priv->family, g_free); | 207 g_clear_pointer (&fontset->priv->family, g_free); |
201 g_clear_pointer (&fontset->priv->language, g_free); | 208 g_clear_pointer (&fontset->priv->language, g_free); |
202 } | 209 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 case PROP_LANGUAGE: | 245 case PROP_LANGUAGE: |
239 g_value_set_string (value, ibus_fontset_get_language (fontset)); | 246 g_value_set_string (value, ibus_fontset_get_language (fontset)); |
240 break; | 247 break; |
241 default: | 248 default: |
242 G_OBJECT_WARN_INVALID_PROPERTY_ID (fontset, prop_id, pspec); | 249 G_OBJECT_WARN_INVALID_PROPERTY_ID (fontset, prop_id, pspec); |
243 } | 250 } |
244 } | 251 } |
245 | 252 |
246 static cairo_scaled_font_t * | 253 static cairo_scaled_font_t * |
247 ibus_fontset_cairo_scaled_font_new_with_font (const gchar *family, | 254 ibus_fontset_cairo_scaled_font_new_with_font (const gchar *family, |
248 guint size) | 255 guint size, |
| 256 gboolean has_color) |
249 { | 257 { |
250 gchar *font_name; | 258 gchar *font_name; |
251 cairo_scaled_font_t *scaled_font = NULL; | 259 cairo_scaled_font_t *scaled_font = NULL; |
252 FcPattern *pattern, *resolved; | 260 FcPattern *pattern, *resolved; |
253 FcResult result; | 261 FcResult result; |
254 cairo_font_options_t *font_options; | 262 cairo_font_options_t *font_options; |
255 double pixel_size = 0.; | 263 double pixel_size = 0.; |
256 FcMatrix fc_matrix, *fc_matrix_val; | 264 FcMatrix fc_matrix, *fc_matrix_val; |
257 cairo_font_face_t *cairo_face = NULL; | 265 cairo_font_face_t *cairo_face = NULL; |
258 cairo_matrix_t font_matrix; | 266 cairo_matrix_t font_matrix; |
259 cairo_matrix_t ctm; | 267 cairo_matrix_t ctm; |
260 int i; | 268 int i; |
261 | 269 |
262 g_return_val_if_fail (family != NULL, NULL); | 270 g_return_val_if_fail (family != NULL, NULL); |
263 g_return_val_if_fail (m_scaled_font_table != NULL, NULL); | 271 g_return_val_if_fail (m_scaled_font_table != NULL, NULL); |
264 | 272 |
265 font_name = g_strdup_printf ("%s %u", family, size); | 273 if (m_color_supported) { |
| 274 font_name = g_strdup_printf ("%s %u:color=%s", |
| 275 family, size, |
| 276 has_color ? "TRUE" : "FALSE"); |
| 277 } else { |
| 278 font_name = g_strdup_printf ("%s %u", family, size); |
| 279 } |
266 scaled_font = g_hash_table_lookup (m_scaled_font_table, font_name); | 280 scaled_font = g_hash_table_lookup (m_scaled_font_table, font_name); |
267 if (scaled_font != NULL) { | 281 if (scaled_font != NULL) { |
268 g_free (font_name); | 282 g_free (font_name); |
269 return scaled_font; | 283 return scaled_font; |
270 } | 284 } |
271 pattern = FcPatternCreate (); | 285 pattern = FcPatternCreate (); |
272 FcPatternAddString (pattern, FC_FAMILY, (FcChar8*) family); | 286 FcPatternAddString (pattern, FC_FAMILY, (FcChar8*) family); |
273 FcPatternAddDouble (pattern, FC_SIZE, (double) size); | 287 FcPatternAddDouble (pattern, FC_SIZE, (double) size); |
| 288 if (m_color_supported) |
| 289 FcPatternAddBool (pattern, FC_COLOR, has_color); |
274 FcPatternAddDouble (pattern, FC_DPI, 96); | 290 FcPatternAddDouble (pattern, FC_DPI, 96); |
275 FcConfigSubstitute(NULL, pattern, FcMatchPattern); | 291 FcConfigSubstitute(NULL, pattern, FcMatchPattern); |
276 font_options = cairo_font_options_create (); | 292 font_options = cairo_font_options_create (); |
277 cairo_ft_font_options_substitute (font_options, pattern); | 293 cairo_ft_font_options_substitute (font_options, pattern); |
278 FcDefaultSubstitute (pattern); | 294 FcDefaultSubstitute (pattern); |
279 resolved = FcFontMatch (NULL, pattern, &result); | 295 resolved = FcFontMatch (NULL, pattern, &result); |
280 FcPatternDestroy (pattern); | 296 FcPatternDestroy (pattern); |
281 FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size); | 297 FcPatternGetDouble (resolved, FC_PIXEL_SIZE, 0, &pixel_size); |
282 if (pixel_size == 0.) | 298 if (pixel_size == 0.) |
283 g_warning ("Failed to scaled the font: %s %u", family, size); | 299 g_warning ("Failed to scaled the font: %s %u", family, size); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 len, &text_extents); | 452 len, &text_extents); |
437 if (text_extents.width) { | 453 if (text_extents.width) { |
438 font_rect->width = pango_units_from_double (text_extents.width); | 454 font_rect->width = pango_units_from_double (text_extents.width); |
439 } else { | 455 } else { |
440 font_rect->width = font_rect->height; | 456 font_rect->width = font_rect->height; |
441 } | 457 } |
442 if (has_unknown_glyph && fallback_family != NULL) { | 458 if (has_unknown_glyph && fallback_family != NULL) { |
443 cairo_scaled_font_t *unknown_font; | 459 cairo_scaled_font_t *unknown_font; |
444 unknown_font = ibus_fontset_cairo_scaled_font_new_with_font ( | 460 unknown_font = ibus_fontset_cairo_scaled_font_new_with_font ( |
445 (const gchar *) fallback_family, | 461 (const gchar *) fallback_family, |
446 UNKNOWN_FONT_SIZE); | 462 UNKNOWN_FONT_SIZE, |
| 463 FALSE); |
447 (*cairo_lines)[n].scaled_font = unknown_font; | 464 (*cairo_lines)[n].scaled_font = unknown_font; |
448 } | 465 } |
449 hb_buffer_destroy (hb_buffer); | 466 hb_buffer_destroy (hb_buffer); |
450 } | 467 } |
451 | 468 |
452 static void | 469 static void |
453 get_string_extents_with_font (const gchar *str, | 470 get_string_extents_with_font (const gchar *str, |
454 FontPerChar *buff, | 471 FontPerChar *buff, |
455 cairo_rectangle_int_t *rect, | 472 cairo_rectangle_int_t *rect, |
456 IBusCairoLine **cairo_lines) | 473 IBusCairoLine **cairo_lines) |
457 { | 474 { |
458 FcChar8 *family = NULL; | 475 FcChar8 *family = NULL; |
459 FcChar8 *font_path = NULL; | 476 FcChar8 *font_path = NULL; |
| 477 gboolean has_color = TRUE; |
460 guint size = 0; | 478 guint size = 0; |
461 cairo_scaled_font_t *scaled_font = NULL; | 479 cairo_scaled_font_t *scaled_font = NULL; |
462 PangoRectangle font_rect = { 0, }; | 480 PangoRectangle font_rect = { 0, }; |
463 hb_font_t *hb_font; | 481 hb_font_t *hb_font; |
464 | 482 |
465 g_return_if_fail (str != NULL); | 483 g_return_if_fail (str != NULL); |
466 g_return_if_fail (buff != NULL && buff->fcfont != NULL); | 484 g_return_if_fail (buff != NULL && buff->fcfont != NULL); |
467 | 485 |
468 FcPatternGetString (buff->fcfont, FC_FAMILY, 0, &family); | 486 FcPatternGetString (buff->fcfont, FC_FAMILY, 0, &family); |
469 g_return_if_fail (family != NULL); | 487 g_return_if_fail (family != NULL); |
| 488 if (m_color_supported) |
| 489 FcPatternGetBool (buff->fcfont, FC_COLOR, 0, &has_color); |
470 size = m_size; | 490 size = m_size; |
471 if (size == 0) { | 491 if (size == 0) { |
472 g_warning ("Font size is not right for font %s.", family); | 492 g_warning ("Font size is not right for font %s.", family); |
473 size = 14; | 493 size = 14; |
474 } | 494 } |
475 scaled_font = ibus_fontset_cairo_scaled_font_new_with_font ( | 495 scaled_font = ibus_fontset_cairo_scaled_font_new_with_font ( |
476 (const gchar *) family, | 496 (const gchar *) family, |
477 size); | 497 size, |
| 498 has_color); |
478 g_return_if_fail (scaled_font != NULL); | 499 g_return_if_fail (scaled_font != NULL); |
479 get_font_extents_with_scaled_font (scaled_font, &font_rect); | 500 get_font_extents_with_scaled_font (scaled_font, &font_rect); |
480 | 501 |
481 FcPatternGetString (buff->fcfont, FC_FILE, 0, &font_path); | 502 FcPatternGetString (buff->fcfont, FC_FILE, 0, &font_path); |
482 g_return_if_fail (font_path != NULL); | 503 g_return_if_fail (font_path != NULL); |
483 hb_font = ibus_fontset_hb_font_new_with_font_path ( | 504 hb_font = ibus_fontset_hb_font_new_with_font_path ( |
484 (const gchar *) font_path); | 505 (const gchar *) font_path); |
485 if (hb_font == NULL) | 506 if (hb_font == NULL) |
486 return; | 507 return; |
487 get_glyph_extents_with_scaled_hb_font (str, | 508 get_glyph_extents_with_scaled_hb_font (str, |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 | 778 |
758 if (g_strcmp0 (family, "")) | 779 if (g_strcmp0 (family, "")) |
759 FcPatternAddString (pattern, FC_FAMILY, (const FcChar8*) family); | 780 FcPatternAddString (pattern, FC_FAMILY, (const FcChar8*) family); |
760 if (size > 0) | 781 if (size > 0) |
761 FcPatternAddDouble (pattern, FC_SIZE, (double) size); | 782 FcPatternAddDouble (pattern, FC_SIZE, (double) size); |
762 if (g_strcmp0 (language, "")) | 783 if (g_strcmp0 (language, "")) |
763 FcPatternAddString (pattern, FC_LANG, (const FcChar8*) language); | 784 FcPatternAddString (pattern, FC_LANG, (const FcChar8*) language); |
764 FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_NORMAL); | 785 FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_NORMAL); |
765 FcPatternAddInteger (pattern, FC_WIDTH, FC_WIDTH_NORMAL); | 786 FcPatternAddInteger (pattern, FC_WIDTH, FC_WIDTH_NORMAL); |
766 FcPatternAddInteger (pattern, FC_DPI, 96); | 787 FcPatternAddInteger (pattern, FC_DPI, 96); |
| 788 if (m_color_supported && |
| 789 (!g_ascii_strncasecmp (family, MONOSPACE, strlen (MONOSPACE)) || |
| 790 !g_ascii_strncasecmp (family, SERIF, strlen (SERIF)) || |
| 791 !g_ascii_strncasecmp (family, SANS, strlen (SANS)))) { |
| 792 FcPatternAddBool (pattern, FC_COLOR, TRUE); |
| 793 } |
767 FcConfigSubstitute (NULL, pattern, FcMatchPattern); | 794 FcConfigSubstitute (NULL, pattern, FcMatchPattern); |
768 FcConfigSubstitute (NULL, pattern, FcMatchFont); | 795 FcConfigSubstitute (NULL, pattern, FcMatchFont); |
769 FcDefaultSubstitute (pattern); | 796 FcDefaultSubstitute (pattern); |
770 m_fcfontset = FcFontSort (NULL, pattern, FcTrue, NULL, &result); | 797 m_fcfontset = FcFontSort (NULL, pattern, FcTrue, NULL, &result); |
| 798 FcPatternDestroy (pattern); |
771 if (result == FcResultNoMatch || m_fcfontset->nfont == 0) { | 799 if (result == FcResultNoMatch || m_fcfontset->nfont == 0) { |
772 g_warning ("No FcFontSet for %s", family ? family : "(null)"); | 800 g_warning ("No FcFontSet for %s", family ? family : "(null)"); |
773 return FALSE; | 801 return FALSE; |
774 } | 802 } |
775 return TRUE; | 803 return TRUE; |
776 } | 804 } |
777 | 805 |
778 void | 806 void |
779 ibus_fontset_unref (IBusFontSet *fontset) | 807 ibus_fontset_unref (IBusFontSet *fontset) |
780 { | 808 { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
913 cairo_set_scaled_font (cr, cairo_lines[i].scaled_font); | 941 cairo_set_scaled_font (cr, cairo_lines[i].scaled_font); |
914 if (num_glyphs > 0 && glyphs[0].index & PANGO_GLYPH_UNKNOWN_FLAG) { | 942 if (num_glyphs > 0 && glyphs[0].index & PANGO_GLYPH_UNKNOWN_FLAG) { |
915 _cairo_show_unknown_glyphs (cr, glyphs, num_glyphs, | 943 _cairo_show_unknown_glyphs (cr, glyphs, num_glyphs, |
916 ex->width, ex->height); | 944 ex->width, ex->height); |
917 } else { | 945 } else { |
918 cairo_show_glyphs (cr, glyphs, num_glyphs); | 946 cairo_show_glyphs (cr, glyphs, num_glyphs); |
919 } | 947 } |
920 cairo_ft_scaled_font_unlock_face (cairo_lines[i].scaled_font); | 948 cairo_ft_scaled_font_unlock_face (cairo_lines[i].scaled_font); |
921 } | 949 } |
922 } | 950 } |
LEFT | RIGHT |