1/* Pango
2 * pangocairofc-font.c: Cairo font handling, fontconfig backend
3 *
4 * Copyright (C) 2000-2005 Red Hat Software
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include "config.h"
23
24/* Freetype has undefined macros in its header */
25#pragma GCC diagnostic push
26#pragma GCC diagnostic ignored "-Wundef"
27#include <cairo-ft.h>
28#pragma GCC diagnostic pop
29
30#include "pangofc-fontmap-private.h"
31#include "pangocairo-private.h"
32#include "pangocairo-fc-private.h"
33#include "pangofc-private.h"
34#include "pango-impl-utils.h"
35
36#include <hb-ot.h>
37#include <freetype/ftmm.h>
38
39#define PANGO_TYPE_CAIRO_FC_FONT (pango_cairo_fc_font_get_type ())
40#define PANGO_CAIRO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFont))
41#define PANGO_CAIRO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
42#define PANGO_CAIRO_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_FC_FONT))
43#define PANGO_CAIRO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFontClass))
44
45typedef struct _PangoCairoFcFont PangoCairoFcFont;
46typedef struct _PangoCairoFcFontClass PangoCairoFcFontClass;
47
48struct _PangoCairoFcFont
49{
50 PangoFcFont font;
51 PangoCairoFontPrivate cf_priv;
52};
53
54struct _PangoCairoFcFontClass
55{
56 PangoFcFontClass parent_class;
57};
58
59_PANGO_EXTERN
60GType pango_cairo_fc_font_get_type (void);
61
62/********************************
63 * Method implementations *
64 ********************************/
65
66static cairo_font_face_t *
67pango_cairo_fc_font_create_font_face (PangoCairoFont *cfont)
68{
69 PangoFcFont *fcfont = (PangoFcFont *) (cfont);
70
71 return cairo_ft_font_face_create_for_pattern (pattern: fcfont->font_pattern);
72}
73
74static PangoFontMetrics *
75pango_cairo_fc_font_create_base_metrics_for_context (PangoCairoFont *cfont,
76 PangoContext *context)
77{
78 PangoCairoFcFont *cffont = (PangoCairoFcFont *) cfont;
79 PangoFcFont *fcfont = (PangoFcFont *) cfont;
80 PangoFontMetrics *metrics;
81
82 metrics = pango_fc_font_create_base_metrics_for_context (font: fcfont, context);
83
84 if (_pango_cairo_font_private_is_metrics_hinted (cf_priv: &cffont->cf_priv))
85 {
86 metrics->ascent = PANGO_PIXELS_CEIL (metrics->ascent) * PANGO_SCALE;
87 metrics->descent = PANGO_PIXELS_CEIL (metrics->descent) * PANGO_SCALE;
88 metrics->height = PANGO_PIXELS_CEIL (metrics->height) * PANGO_SCALE;
89 }
90
91 return metrics;
92}
93
94static void
95cairo_font_iface_init (PangoCairoFontIface *iface)
96{
97 iface->create_font_face = pango_cairo_fc_font_create_font_face;
98 iface->create_base_metrics_for_context = pango_cairo_fc_font_create_base_metrics_for_context;
99 iface->cf_priv_offset = G_STRUCT_OFFSET (PangoCairoFcFont, cf_priv);
100}
101
102G_DEFINE_TYPE_WITH_CODE (PangoCairoFcFont, pango_cairo_fc_font, PANGO_TYPE_FC_FONT,
103 { G_IMPLEMENT_INTERFACE (PANGO_TYPE_CAIRO_FONT, cairo_font_iface_init) })
104
105static void
106pango_cairo_fc_font_finalize (GObject *object)
107{
108 PangoCairoFcFont *cffont = (PangoCairoFcFont *) object;
109
110 _pango_cairo_font_private_finalize (cf_priv: &cffont->cf_priv);
111
112 G_OBJECT_CLASS (pango_cairo_fc_font_parent_class)->finalize (object);
113}
114
115/* we want get_glyph_extents extremely fast, so we use a small wrapper here
116 * to avoid having to lookup the interface data like we do for get_metrics
117 * in _pango_cairo_font_get_metrics(). */
118static void
119pango_cairo_fc_font_get_glyph_extents (PangoFont *font,
120 PangoGlyph glyph,
121 PangoRectangle *ink_rect,
122 PangoRectangle *logical_rect)
123{
124 PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
125
126 _pango_cairo_font_private_get_glyph_extents (cf_priv: &cffont->cf_priv,
127 glyph,
128 ink_rect,
129 logical_rect);
130}
131
132static FT_Face
133pango_cairo_fc_font_lock_face (PangoFcFont *font)
134{
135 PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
136 cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv: &cffont->cf_priv);
137
138 if (G_UNLIKELY (!scaled_font))
139 return NULL;
140
141 return cairo_ft_scaled_font_lock_face (scaled_font);
142}
143
144static void
145pango_cairo_fc_font_unlock_face (PangoFcFont *font)
146{
147 PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
148 cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (cf_priv: &cffont->cf_priv);
149
150 if (G_UNLIKELY (!scaled_font))
151 return;
152
153 cairo_ft_scaled_font_unlock_face (scaled_font);
154}
155
156static void
157pango_cairo_fc_font_class_init (PangoCairoFcFontClass *class)
158{
159 GObjectClass *object_class = G_OBJECT_CLASS (class);
160 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
161 PangoFcFontClass *fc_font_class = PANGO_FC_FONT_CLASS (class);
162
163 object_class->finalize = pango_cairo_fc_font_finalize;
164
165 font_class->get_glyph_extents = pango_cairo_fc_font_get_glyph_extents;
166 font_class->get_metrics = _pango_cairo_font_get_metrics;
167
168 fc_font_class->lock_face = pango_cairo_fc_font_lock_face;
169 fc_font_class->unlock_face = pango_cairo_fc_font_unlock_face;
170}
171
172static void
173pango_cairo_fc_font_init (PangoCairoFcFont *cffont G_GNUC_UNUSED)
174{
175}
176
177/********************
178 * Private API *
179 ********************/
180
181static double
182get_font_size (const FcPattern *pattern)
183{
184 double size;
185 double dpi;
186
187 if (FcPatternGetDouble (p: pattern, FC_PIXEL_SIZE, n: 0, d: &size) == FcResultMatch)
188 return size;
189
190 /* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern()
191 * and here. That would be very weird.
192 */
193
194 if (FcPatternGetDouble (p: pattern, FC_DPI, n: 0, d: &dpi) != FcResultMatch)
195 dpi = 72;
196
197 if (FcPatternGetDouble (p: pattern, FC_SIZE, n: 0, d: &size) == FcResultMatch)
198 return size * dpi / 72.;
199
200 /* Whatever */
201 return 18.;
202}
203
204static gpointer
205get_gravity_class (void)
206{
207 static GEnumClass *class = NULL; /* MT-safe */
208
209 if (g_once_init_enter (&class))
210 g_once_init_leave(&class, (gpointer)g_type_class_ref (PANGO_TYPE_GRAVITY));
211
212 return class;
213}
214
215static PangoGravity
216get_gravity (const FcPattern *pattern)
217{
218 char *s;
219
220 if (FcPatternGetString (p: pattern, PANGO_FC_GRAVITY, n: 0, s: (FcChar8 **)(void *)&s) == FcResultMatch)
221 {
222 GEnumValue *value = g_enum_get_value_by_nick (enum_class: get_gravity_class (), nick: s);
223 return value->value;
224 }
225
226 return PANGO_GRAVITY_SOUTH;
227}
228
229PangoFcFont *
230_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
231 PangoFcFontKey *key)
232{
233 PangoCairoFcFont *cffont;
234 const FcPattern *pattern = pango_fc_font_key_get_pattern (key);
235 cairo_matrix_t font_matrix;
236 FcMatrix fc_matrix, *fc_matrix_val;
237 double size;
238 int i;
239 cairo_font_options_t *options;
240
241 g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (cffontmap), NULL);
242 g_return_val_if_fail (pattern != NULL, NULL);
243
244 cffont = g_object_new (PANGO_TYPE_CAIRO_FC_FONT,
245 first_property_name: "pattern", pattern,
246 "fontmap", cffontmap,
247 NULL);
248
249 size = get_font_size (pattern) /
250 pango_matrix_get_font_scale_factor (matrix: pango_fc_font_key_get_matrix (key));
251
252 FcMatrixInit (&fc_matrix);
253 for (i = 0; FcPatternGetMatrix (p: pattern, FC_MATRIX, n: i, s: &fc_matrix_val) == FcResultMatch; i++)
254 FcMatrixMultiply (result: &fc_matrix, a: &fc_matrix, b: fc_matrix_val);
255
256 cairo_matrix_init (matrix: &font_matrix,
257 xx: fc_matrix.xx,
258 yx: - fc_matrix.yx,
259 xy: - fc_matrix.xy,
260 yy: fc_matrix.yy,
261 x0: 0., y0: 0.);
262
263 cairo_matrix_scale (matrix: &font_matrix, sx: size, sy: size);
264
265 options = pango_fc_font_key_get_context_key (key);
266
267 _pango_cairo_font_private_initialize (cf_priv: &cffont->cf_priv,
268 font: (PangoCairoFont *) cffont,
269 gravity: get_gravity (pattern),
270 font_options: options,
271 pango_ctm: pango_fc_font_key_get_matrix (key),
272 font_matrix: &font_matrix);
273
274 ((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (cf_priv: &cffont->cf_priv);
275
276 return (PangoFcFont *) cffont;
277}
278

source code of gtk/subprojects/pango/pango/pangocairo-fcfont.c