• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2012  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #include "hb-private.hh"
30 
31 #include "hb-face-private.hh"
32 #include "hb-open-file-private.hh"
33 #include "hb-ot-head-table.hh"
34 #include "hb-ot-maxp-table.hh"
35 
36 
37 /*
38  * hb_face_t
39  */
40 
41 const hb_face_t _hb_face_nil = {
42   HB_OBJECT_HEADER_STATIC,
43 
44   true, /* immutable */
45 
46   NULL, /* reference_table_func */
47   NULL, /* user_data */
48   NULL, /* destroy */
49 
50   0,    /* index */
51   1000, /* upem */
52   0,    /* num_glyphs */
53 
54   {
55 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
56 #include "hb-shaper-list.hh"
57 #undef HB_SHAPER_IMPLEMENT
58   },
59 
60   NULL, /* shape_plans */
61 };
62 
63 
64 /**
65  * hb_face_create_for_tables:
66  * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
67  * @user_data:
68  * @destroy:
69  *
70  *
71  *
72  * Return value: (transfer full)
73  *
74  * Since: 0.9.2
75  **/
76 hb_face_t *
hb_face_create_for_tables(hb_reference_table_func_t reference_table_func,void * user_data,hb_destroy_func_t destroy)77 hb_face_create_for_tables (hb_reference_table_func_t  reference_table_func,
78 			   void                      *user_data,
79 			   hb_destroy_func_t          destroy)
80 {
81   hb_face_t *face;
82 
83   if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
84     if (destroy)
85       destroy (user_data);
86     return hb_face_get_empty ();
87   }
88 
89   face->reference_table_func = reference_table_func;
90   face->user_data = user_data;
91   face->destroy = destroy;
92 
93   face->upem = 0;
94   face->num_glyphs = (unsigned int) -1;
95 
96   return face;
97 }
98 
99 
100 typedef struct hb_face_for_data_closure_t {
101   hb_blob_t *blob;
102   unsigned int  index;
103 } hb_face_for_data_closure_t;
104 
105 static hb_face_for_data_closure_t *
_hb_face_for_data_closure_create(hb_blob_t * blob,unsigned int index)106 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
107 {
108   hb_face_for_data_closure_t *closure;
109 
110   closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
111   if (unlikely (!closure))
112     return NULL;
113 
114   closure->blob = blob;
115   closure->index = index;
116 
117   return closure;
118 }
119 
120 static void
_hb_face_for_data_closure_destroy(hb_face_for_data_closure_t * closure)121 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
122 {
123   hb_blob_destroy (closure->blob);
124   free (closure);
125 }
126 
127 static hb_blob_t *
_hb_face_for_data_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)128 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
129 {
130   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
131 
132   if (tag == HB_TAG_NONE)
133     return hb_blob_reference (data->blob);
134 
135   const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
136   const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
137 
138   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
139 
140   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
141 
142   return blob;
143 }
144 
145 /**
146  * hb_face_create: (Xconstructor)
147  * @blob:
148  * @index:
149  *
150  *
151  *
152  * Return value: (transfer full):
153  *
154  * Since: 0.9.2
155  **/
156 hb_face_t *
hb_face_create(hb_blob_t * blob,unsigned int index)157 hb_face_create (hb_blob_t    *blob,
158 		unsigned int  index)
159 {
160   hb_face_t *face;
161 
162   if (unlikely (!blob))
163     blob = hb_blob_get_empty ();
164 
165   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
166 
167   if (unlikely (!closure))
168     return hb_face_get_empty ();
169 
170   face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
171 				    closure,
172 				    (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
173 
174   hb_face_set_index (face, index);
175 
176   return face;
177 }
178 
179 /**
180  * hb_face_get_empty:
181  *
182  *
183  *
184  * Return value: (transfer full)
185  *
186  * Since: 0.9.2
187  **/
188 hb_face_t *
hb_face_get_empty(void)189 hb_face_get_empty (void)
190 {
191   return const_cast<hb_face_t *> (&_hb_face_nil);
192 }
193 
194 
195 /**
196  * hb_face_reference: (skip)
197  * @face: a face.
198  *
199  *
200  *
201  * Return value:
202  *
203  * Since: 0.9.2
204  **/
205 hb_face_t *
hb_face_reference(hb_face_t * face)206 hb_face_reference (hb_face_t *face)
207 {
208   return hb_object_reference (face);
209 }
210 
211 /**
212  * hb_face_destroy: (skip)
213  * @face: a face.
214  *
215  *
216  *
217  * Since: 0.9.2
218  **/
219 void
hb_face_destroy(hb_face_t * face)220 hb_face_destroy (hb_face_t *face)
221 {
222   if (!hb_object_destroy (face)) return;
223 
224   for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
225   {
226     hb_face_t::plan_node_t *next = node->next;
227     hb_shape_plan_destroy (node->shape_plan);
228     free (node);
229     node = next;
230   }
231 
232 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
233 #include "hb-shaper-list.hh"
234 #undef HB_SHAPER_IMPLEMENT
235 
236   if (face->destroy)
237     face->destroy (face->user_data);
238 
239   free (face);
240 }
241 
242 /**
243  * hb_face_set_user_data: (skip)
244  * @face: a face.
245  * @key:
246  * @data:
247  * @destroy:
248  * @replace:
249  *
250  *
251  *
252  * Return value:
253  *
254  * Since: 0.9.2
255  **/
256 hb_bool_t
hb_face_set_user_data(hb_face_t * face,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)257 hb_face_set_user_data (hb_face_t          *face,
258 		       hb_user_data_key_t *key,
259 		       void *              data,
260 		       hb_destroy_func_t   destroy,
261 		       hb_bool_t           replace)
262 {
263   return hb_object_set_user_data (face, key, data, destroy, replace);
264 }
265 
266 /**
267  * hb_face_get_user_data: (skip)
268  * @face: a face.
269  * @key:
270  *
271  *
272  *
273  * Return value: (transfer none):
274  *
275  * Since: 0.9.2
276  **/
277 void *
hb_face_get_user_data(hb_face_t * face,hb_user_data_key_t * key)278 hb_face_get_user_data (hb_face_t          *face,
279 		       hb_user_data_key_t *key)
280 {
281   return hb_object_get_user_data (face, key);
282 }
283 
284 /**
285  * hb_face_make_immutable:
286  * @face: a face.
287  *
288  *
289  *
290  * Since: 0.9.2
291  **/
292 void
hb_face_make_immutable(hb_face_t * face)293 hb_face_make_immutable (hb_face_t *face)
294 {
295   if (unlikely (hb_object_is_inert (face)))
296     return;
297 
298   face->immutable = true;
299 }
300 
301 /**
302  * hb_face_is_immutable:
303  * @face: a face.
304  *
305  *
306  *
307  * Return value:
308  *
309  * Since: 0.9.2
310  **/
311 hb_bool_t
hb_face_is_immutable(hb_face_t * face)312 hb_face_is_immutable (hb_face_t *face)
313 {
314   return face->immutable;
315 }
316 
317 
318 /**
319  * hb_face_reference_table:
320  * @face: a face.
321  * @tag:
322  *
323  *
324  *
325  * Return value: (transfer full):
326  *
327  * Since: 0.9.2
328  **/
329 hb_blob_t *
hb_face_reference_table(hb_face_t * face,hb_tag_t tag)330 hb_face_reference_table (hb_face_t *face,
331 			 hb_tag_t   tag)
332 {
333   return face->reference_table (tag);
334 }
335 
336 /**
337  * hb_face_reference_blob:
338  * @face: a face.
339  *
340  *
341  *
342  * Return value: (transfer full):
343  *
344  * Since: 0.9.2
345  **/
346 hb_blob_t *
hb_face_reference_blob(hb_face_t * face)347 hb_face_reference_blob (hb_face_t *face)
348 {
349   return face->reference_table (HB_TAG_NONE);
350 }
351 
352 /**
353  * hb_face_set_index:
354  * @face: a face.
355  * @index:
356  *
357  *
358  *
359  * Since: 0.9.2
360  **/
361 void
hb_face_set_index(hb_face_t * face,unsigned int index)362 hb_face_set_index (hb_face_t    *face,
363 		   unsigned int  index)
364 {
365   if (face->immutable)
366     return;
367 
368   face->index = index;
369 }
370 
371 /**
372  * hb_face_get_index:
373  * @face: a face.
374  *
375  *
376  *
377  * Return value:
378  *
379  * Since: 0.9.2
380  **/
381 unsigned int
hb_face_get_index(hb_face_t * face)382 hb_face_get_index (hb_face_t    *face)
383 {
384   return face->index;
385 }
386 
387 /**
388  * hb_face_set_upem:
389  * @face: a face.
390  * @upem:
391  *
392  *
393  *
394  * Since: 0.9.2
395  **/
396 void
hb_face_set_upem(hb_face_t * face,unsigned int upem)397 hb_face_set_upem (hb_face_t    *face,
398 		  unsigned int  upem)
399 {
400   if (face->immutable)
401     return;
402 
403   face->upem = upem;
404 }
405 
406 /**
407  * hb_face_get_upem:
408  * @face: a face.
409  *
410  *
411  *
412  * Return value:
413  *
414  * Since: 0.9.2
415  **/
416 unsigned int
hb_face_get_upem(hb_face_t * face)417 hb_face_get_upem (hb_face_t *face)
418 {
419   return face->get_upem ();
420 }
421 
422 void
load_upem(void) const423 hb_face_t::load_upem (void) const
424 {
425   hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
426   const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
427   upem = head_table->get_upem ();
428   hb_blob_destroy (head_blob);
429 }
430 
431 /**
432  * hb_face_set_glyph_count:
433  * @face: a face.
434  * @glyph_count:
435  *
436  *
437  *
438  * Since: 0.9.7
439  **/
440 void
hb_face_set_glyph_count(hb_face_t * face,unsigned int glyph_count)441 hb_face_set_glyph_count (hb_face_t    *face,
442 			 unsigned int  glyph_count)
443 {
444   if (face->immutable)
445     return;
446 
447   face->num_glyphs = glyph_count;
448 }
449 
450 /**
451  * hb_face_get_glyph_count:
452  * @face: a face.
453  *
454  *
455  *
456  * Return value:
457  *
458  * Since: 0.9.7
459  **/
460 unsigned int
hb_face_get_glyph_count(hb_face_t * face)461 hb_face_get_glyph_count (hb_face_t *face)
462 {
463   return face->get_num_glyphs ();
464 }
465 
466 void
load_num_glyphs(void) const467 hb_face_t::load_num_glyphs (void) const
468 {
469   hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
470   const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
471   num_glyphs = maxp_table->get_num_glyphs ();
472   hb_blob_destroy (maxp_blob);
473 }
474 
475 
476