1 /* Pango
2 * pangocoretext.c
3 *
4 * Copyright (C) 2005-2007 Imendio AB
5 * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23 #include "config.h"
24
25 #include "pangocoretext.h"
26 #include "pangocoretext-private.h"
27 #include <hb-coretext.h>
28
29 struct _PangoCoreTextFontPrivate
30 {
31 gpointer context_key;
32
33 CTFontRef font_ref;
34 PangoCoreTextFontKey *key;
35
36 PangoCoverage *coverage;
37
38 PangoFontMap *fontmap;
39 };
40
G_DEFINE_TYPE_WITH_PRIVATE(PangoCoreTextFont,pango_core_text_font,PANGO_TYPE_FONT)41 G_DEFINE_TYPE_WITH_PRIVATE (PangoCoreTextFont, pango_core_text_font, PANGO_TYPE_FONT)
42
43 static void
44 pango_core_text_font_finalize (GObject *object)
45 {
46 PangoCoreTextFont *ctfont = (PangoCoreTextFont *)object;
47 PangoCoreTextFontPrivate *priv = ctfont->priv;
48 PangoCoreTextFontMap* fontmap = g_weak_ref_get ((GWeakRef *)&priv->fontmap);
49 if (fontmap)
50 {
51 g_weak_ref_clear ((GWeakRef *)&priv->fontmap);
52 g_object_unref (fontmap);
53 }
54
55 if (priv->coverage)
56 pango_coverage_unref (priv->coverage);
57
58 G_OBJECT_CLASS (pango_core_text_font_parent_class)->finalize (object);
59 }
60
61 static PangoFontDescription *
pango_core_text_font_describe(PangoFont * font)62 pango_core_text_font_describe (PangoFont *font)
63 {
64 PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font;
65 PangoCoreTextFontPrivate *priv = ctfont->priv;
66 CTFontDescriptorRef ctfontdesc;
67
68 ctfontdesc = pango_core_text_font_key_get_ctfontdescriptor (priv->key);
69
70 return _pango_core_text_font_description_from_ct_font_descriptor (ctfontdesc);
71 }
72
73 static PangoCoverage *
ct_font_descriptor_get_coverage(CTFontDescriptorRef desc)74 ct_font_descriptor_get_coverage (CTFontDescriptorRef desc)
75 {
76 CFCharacterSetRef charset;
77 CFIndex i, length;
78 CFDataRef bitmap;
79 const UInt8 *ptr, *plane_ptr;
80 const UInt32 plane_size = 8192;
81 PangoCoverage *coverage;
82
83 coverage = pango_coverage_new ();
84
85 charset = CTFontDescriptorCopyAttribute (desc, kCTFontCharacterSetAttribute);
86 if (!charset)
87 /* Return an empty coverage */
88 return coverage;
89
90 bitmap = CFCharacterSetCreateBitmapRepresentation (kCFAllocatorDefault,
91 charset);
92 ptr = CFDataGetBytePtr (bitmap);
93
94 /* First handle the BMP plane. */
95 length = MIN (CFDataGetLength (bitmap), plane_size);
96
97 /* FIXME: can and should this be done more efficiently? */
98 for (i = 0; i < length; i++)
99 {
100 int j;
101
102 for (j = 0; j < 8; j++)
103 if ((ptr[i] & (1 << j)) == (1 << j))
104 pango_coverage_set (coverage, i * 8 + j, PANGO_COVERAGE_EXACT);
105 }
106
107 /* Next, handle the other planes. The plane number is encoded first as
108 * a single byte. In the following 8192 bytes that plane's coverage bitmap
109 * is stored.
110 */
111 plane_ptr = ptr + plane_size;
112 while (plane_ptr - ptr < CFDataGetLength (bitmap))
113 {
114 const UInt8 plane_number = *plane_ptr;
115 plane_ptr++;
116
117 for (i = 0; i < plane_size; i++)
118 {
119 int j;
120
121 for (j = 0; j < 8; j++)
122 if ((plane_ptr[i] & (1 << j)) == (1 << j))
123 pango_coverage_set (coverage, (plane_number * plane_size + i) * 8 + j,
124 PANGO_COVERAGE_EXACT);
125 }
126
127 plane_ptr += plane_size;
128 }
129
130 CFRelease (bitmap);
131 CFRelease (charset);
132
133 return coverage;
134 }
135
136 static PangoCoverage *
pango_core_text_font_get_coverage(PangoFont * font,PangoLanguage * language G_GNUC_UNUSED)137 pango_core_text_font_get_coverage (PangoFont *font,
138 PangoLanguage *language G_GNUC_UNUSED)
139 {
140 PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font;
141 PangoCoreTextFontPrivate *priv = ctfont->priv;
142
143 if (!priv->coverage)
144 {
145 CTFontDescriptorRef ctfontdesc;
146
147 ctfontdesc = pango_core_text_font_key_get_ctfontdescriptor (priv->key);
148
149 priv->coverage = ct_font_descriptor_get_coverage (ctfontdesc);
150 }
151
152 return pango_coverage_ref (priv->coverage);
153 }
154
155 static PangoFontMap *
pango_core_text_font_get_font_map(PangoFont * font)156 pango_core_text_font_get_font_map (PangoFont *font)
157 {
158 PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font;
159 /* FIXME: Not thread safe! */
160 return ctfont->priv->fontmap;
161 }
162
163 static hb_font_t *
pango_core_text_font_create_hb_font(PangoFont * font)164 pango_core_text_font_create_hb_font (PangoFont *font)
165 {
166 PangoCoreTextFont *ctfont = (PangoCoreTextFont *)font;
167
168 if (ctfont->priv->font_ref)
169 {
170 const PangoMatrix *matrix;
171 hb_font_t *hb_font;
172 double x_scale, y_scale;
173 int size;
174
175 matrix = pango_core_text_font_key_get_matrix (ctfont->priv->key);
176 pango_matrix_get_font_scale_factors (matrix, &x_scale, &y_scale);
177 size = pango_core_text_font_key_get_size (ctfont->priv->key);
178 hb_font = hb_coretext_font_create (ctfont->priv->font_ref);
179 hb_font_set_scale (hb_font, size / x_scale, size / y_scale);
180
181 return hb_font;
182 }
183
184 return hb_font_get_empty ();
185 }
186
187 static void
pango_core_text_font_init(PangoCoreTextFont * ctfont)188 pango_core_text_font_init (PangoCoreTextFont *ctfont)
189 {
190 ctfont->priv = pango_core_text_font_get_instance_private (ctfont);
191 }
192
193 static void
pango_core_text_font_class_init(PangoCoreTextFontClass * class)194 pango_core_text_font_class_init (PangoCoreTextFontClass *class)
195 {
196 GObjectClass *object_class = G_OBJECT_CLASS (class);
197 PangoFontClass *font_class = PANGO_FONT_CLASS (class);
198
199 object_class->finalize = pango_core_text_font_finalize;
200
201 font_class->describe = pango_core_text_font_describe;
202 /* font_class->describe_absolute is left virtual for PangoCairoCoreTextFont. */
203 font_class->get_coverage = pango_core_text_font_get_coverage;
204 font_class->get_font_map = pango_core_text_font_get_font_map;
205 font_class->create_hb_font = pango_core_text_font_create_hb_font;
206 }
207
208 void
_pango_core_text_font_set_font_map(PangoCoreTextFont * font,PangoCoreTextFontMap * fontmap)209 _pango_core_text_font_set_font_map (PangoCoreTextFont *font,
210 PangoCoreTextFontMap *fontmap)
211 {
212 PangoCoreTextFontPrivate *priv = font->priv;
213
214 g_return_if_fail (priv->fontmap == NULL);
215 g_weak_ref_set((GWeakRef *) &priv->fontmap, fontmap);
216 }
217
218 PangoCoreTextFace *
_pango_core_text_font_get_face(PangoCoreTextFont * font)219 _pango_core_text_font_get_face (PangoCoreTextFont *font)
220 {
221 PangoCoreTextFontPrivate *priv = font->priv;
222
223 return pango_core_text_font_map_find_face (PANGO_CORE_TEXT_FONT_MAP (priv->fontmap), priv->key);
224 }
225
226 gpointer
_pango_core_text_font_get_context_key(PangoCoreTextFont * font)227 _pango_core_text_font_get_context_key (PangoCoreTextFont *font)
228 {
229 PangoCoreTextFontPrivate *priv = font->priv;
230
231 return priv->context_key;
232 }
233
234 void
_pango_core_text_font_set_context_key(PangoCoreTextFont * font,gpointer context_key)235 _pango_core_text_font_set_context_key (PangoCoreTextFont *font,
236 gpointer context_key)
237 {
238 PangoCoreTextFontPrivate *priv = font->priv;
239
240 priv->context_key = context_key;
241 }
242
243 void
_pango_core_text_font_set_font_key(PangoCoreTextFont * font,PangoCoreTextFontKey * key)244 _pango_core_text_font_set_font_key (PangoCoreTextFont *font,
245 PangoCoreTextFontKey *key)
246 {
247 PangoCoreTextFontPrivate *priv = font->priv;
248
249 priv->key = key;
250
251 if (priv->coverage)
252 {
253 pango_coverage_unref (priv->coverage);
254 priv->coverage = NULL;
255 }
256 }
257
258 void
_pango_core_text_font_set_ctfont(PangoCoreTextFont * font,CTFontRef font_ref)259 _pango_core_text_font_set_ctfont (PangoCoreTextFont *font,
260 CTFontRef font_ref)
261 {
262 PangoCoreTextFontPrivate *priv = font->priv;
263
264 priv->font_ref = font_ref;
265 }
266
267 /**
268 * pango_core_text_font_get_ctfont:
269 * @font: A `PangoCoreTextFont`
270 *
271 * Returns the CTFontRef of a font.
272 *
273 * Return value: the CTFontRef associated to @font.
274 *
275 * Since: 1.24
276 */
277 CTFontRef
pango_core_text_font_get_ctfont(PangoCoreTextFont * font)278 pango_core_text_font_get_ctfont (PangoCoreTextFont *font)
279 {
280 PangoCoreTextFontPrivate *priv = font->priv;
281
282 return priv->font_ref;
283 }
284