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