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-ot-layout-private.hh"
32
33 #include "hb-font-private.hh"
34 #include "hb-blob.h"
35 #include "hb-open-file-private.hh"
36 #include "hb-ot-head-table.hh"
37 #include "hb-ot-maxp-table.hh"
38
39 #include "hb-cache-private.hh"
40
41 #include <string.h>
42
43
44 /*
45 * hb_face_t
46 */
47
48 const hb_face_t _hb_face_nil = {
49 HB_OBJECT_HEADER_STATIC,
50
51 true, /* immutable */
52
53 NULL, /* reference_table_func */
54 NULL, /* user_data */
55 NULL, /* destroy */
56
57 0, /* index */
58 1000, /* upem */
59 0, /* num_glyphs */
60
61 {
62 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
63 #include "hb-shaper-list.hh"
64 #undef HB_SHAPER_IMPLEMENT
65 },
66
67 NULL, /* shape_plans */
68 };
69
70
71 /**
72 * hb_face_create_for_tables:
73 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
74 * @user_data:
75 * @destroy:
76 *
77 *
78 *
79 * Return value: (transfer full)
80 *
81 * Since: 1.0
82 **/
83 hb_face_t *
hb_face_create_for_tables(hb_reference_table_func_t reference_table_func,void * user_data,hb_destroy_func_t destroy)84 hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
85 void *user_data,
86 hb_destroy_func_t destroy)
87 {
88 hb_face_t *face;
89
90 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
91 if (destroy)
92 destroy (user_data);
93 return hb_face_get_empty ();
94 }
95
96 face->reference_table_func = reference_table_func;
97 face->user_data = user_data;
98 face->destroy = destroy;
99
100 face->upem = 0;
101 face->num_glyphs = (unsigned int) -1;
102
103 return face;
104 }
105
106
107 typedef struct hb_face_for_data_closure_t {
108 hb_blob_t *blob;
109 unsigned int index;
110 } hb_face_for_data_closure_t;
111
112 static hb_face_for_data_closure_t *
_hb_face_for_data_closure_create(hb_blob_t * blob,unsigned int index)113 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
114 {
115 hb_face_for_data_closure_t *closure;
116
117 closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
118 if (unlikely (!closure))
119 return NULL;
120
121 closure->blob = blob;
122 closure->index = index;
123
124 return closure;
125 }
126
127 static void
_hb_face_for_data_closure_destroy(hb_face_for_data_closure_t * closure)128 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
129 {
130 hb_blob_destroy (closure->blob);
131 free (closure);
132 }
133
134 static hb_blob_t *
_hb_face_for_data_reference_table(hb_face_t * face HB_UNUSED,hb_tag_t tag,void * user_data)135 _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
136 {
137 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
138
139 if (tag == HB_TAG_NONE)
140 return hb_blob_reference (data->blob);
141
142 const OT::OpenTypeFontFile &ot_file = *OT::Sanitizer<OT::OpenTypeFontFile>::lock_instance (data->blob);
143 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
144
145 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
146
147 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
148
149 return blob;
150 }
151
152 /**
153 * hb_face_create: (Xconstructor)
154 * @blob:
155 * @index:
156 *
157 *
158 *
159 * Return value: (transfer full):
160 *
161 * Since: 1.0
162 **/
163 hb_face_t *
hb_face_create(hb_blob_t * blob,unsigned int index)164 hb_face_create (hb_blob_t *blob,
165 unsigned int index)
166 {
167 hb_face_t *face;
168
169 if (unlikely (!blob || !hb_blob_get_length (blob)))
170 return hb_face_get_empty ();
171
172 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
173
174 if (unlikely (!closure))
175 return hb_face_get_empty ();
176
177 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
178 closure,
179 (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
180
181 hb_face_set_index (face, index);
182
183 return face;
184 }
185
186 /**
187 * hb_face_get_empty:
188 *
189 *
190 *
191 * Return value: (transfer full)
192 *
193 * Since: 1.0
194 **/
195 hb_face_t *
hb_face_get_empty(void)196 hb_face_get_empty (void)
197 {
198 return const_cast<hb_face_t *> (&_hb_face_nil);
199 }
200
201
202 /**
203 * hb_face_reference: (skip)
204 * @face: a face.
205 *
206 *
207 *
208 * Return value:
209 *
210 * Since: 1.0
211 **/
212 hb_face_t *
hb_face_reference(hb_face_t * face)213 hb_face_reference (hb_face_t *face)
214 {
215 return hb_object_reference (face);
216 }
217
218 /**
219 * hb_face_destroy: (skip)
220 * @face: a face.
221 *
222 *
223 *
224 * Since: 1.0
225 **/
226 void
hb_face_destroy(hb_face_t * face)227 hb_face_destroy (hb_face_t *face)
228 {
229 if (!hb_object_destroy (face)) return;
230
231 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
232 {
233 hb_face_t::plan_node_t *next = node->next;
234 hb_shape_plan_destroy (node->shape_plan);
235 free (node);
236 node = next;
237 }
238
239 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
240 #include "hb-shaper-list.hh"
241 #undef HB_SHAPER_IMPLEMENT
242
243 if (face->destroy)
244 face->destroy (face->user_data);
245
246 free (face);
247 }
248
249 /**
250 * hb_face_set_user_data: (skip)
251 * @face: a face.
252 * @key:
253 * @data:
254 * @destroy:
255 * @replace:
256 *
257 *
258 *
259 * Return value:
260 *
261 * Since: 1.0
262 **/
263 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)264 hb_face_set_user_data (hb_face_t *face,
265 hb_user_data_key_t *key,
266 void * data,
267 hb_destroy_func_t destroy,
268 hb_bool_t replace)
269 {
270 return hb_object_set_user_data (face, key, data, destroy, replace);
271 }
272
273 /**
274 * hb_face_get_user_data: (skip)
275 * @face: a face.
276 * @key:
277 *
278 *
279 *
280 * Return value: (transfer none):
281 *
282 * Since: 1.0
283 **/
284 void *
hb_face_get_user_data(hb_face_t * face,hb_user_data_key_t * key)285 hb_face_get_user_data (hb_face_t *face,
286 hb_user_data_key_t *key)
287 {
288 return hb_object_get_user_data (face, key);
289 }
290
291 /**
292 * hb_face_make_immutable:
293 * @face: a face.
294 *
295 *
296 *
297 * Since: 1.0
298 **/
299 void
hb_face_make_immutable(hb_face_t * face)300 hb_face_make_immutable (hb_face_t *face)
301 {
302 if (hb_object_is_inert (face))
303 return;
304
305 face->immutable = true;
306 }
307
308 /**
309 * hb_face_is_immutable:
310 * @face: a face.
311 *
312 *
313 *
314 * Return value:
315 *
316 * Since: 1.0
317 **/
318 hb_bool_t
hb_face_is_immutable(hb_face_t * face)319 hb_face_is_immutable (hb_face_t *face)
320 {
321 return face->immutable;
322 }
323
324
325 /**
326 * hb_face_reference_table:
327 * @face: a face.
328 * @tag:
329 *
330 *
331 *
332 * Return value: (transfer full):
333 *
334 * Since: 1.0
335 **/
336 hb_blob_t *
hb_face_reference_table(hb_face_t * face,hb_tag_t tag)337 hb_face_reference_table (hb_face_t *face,
338 hb_tag_t tag)
339 {
340 return face->reference_table (tag);
341 }
342
343 /**
344 * hb_face_reference_blob:
345 * @face: a face.
346 *
347 *
348 *
349 * Return value: (transfer full):
350 *
351 * Since: 1.0
352 **/
353 hb_blob_t *
hb_face_reference_blob(hb_face_t * face)354 hb_face_reference_blob (hb_face_t *face)
355 {
356 return face->reference_table (HB_TAG_NONE);
357 }
358
359 /**
360 * hb_face_set_index:
361 * @face: a face.
362 * @index:
363 *
364 *
365 *
366 * Since: 1.0
367 **/
368 void
hb_face_set_index(hb_face_t * face,unsigned int index)369 hb_face_set_index (hb_face_t *face,
370 unsigned int index)
371 {
372 if (hb_object_is_inert (face))
373 return;
374
375 face->index = index;
376 }
377
378 /**
379 * hb_face_get_index:
380 * @face: a face.
381 *
382 *
383 *
384 * Return value:
385 *
386 * Since: 1.0
387 **/
388 unsigned int
hb_face_get_index(hb_face_t * face)389 hb_face_get_index (hb_face_t *face)
390 {
391 return face->index;
392 }
393
394 /**
395 * hb_face_set_upem:
396 * @face: a face.
397 * @upem:
398 *
399 *
400 *
401 * Since: 1.0
402 **/
403 void
hb_face_set_upem(hb_face_t * face,unsigned int upem)404 hb_face_set_upem (hb_face_t *face,
405 unsigned int upem)
406 {
407 if (hb_object_is_inert (face))
408 return;
409
410 face->upem = upem;
411 }
412
413 /**
414 * hb_face_get_upem:
415 * @face: a face.
416 *
417 *
418 *
419 * Return value:
420 *
421 * Since: 1.0
422 **/
423 unsigned int
hb_face_get_upem(hb_face_t * face)424 hb_face_get_upem (hb_face_t *face)
425 {
426 return face->get_upem ();
427 }
428
429 void
load_upem(void) const430 hb_face_t::load_upem (void) const
431 {
432 hb_blob_t *head_blob = OT::Sanitizer<OT::head>::sanitize (reference_table (HB_OT_TAG_head));
433 const OT::head *head_table = OT::Sanitizer<OT::head>::lock_instance (head_blob);
434 upem = head_table->get_upem ();
435 hb_blob_destroy (head_blob);
436 }
437
438 /**
439 * hb_face_set_glyph_count:
440 * @face: a face.
441 * @glyph_count:
442 *
443 *
444 *
445 * Since: 1.0
446 **/
447 void
hb_face_set_glyph_count(hb_face_t * face,unsigned int glyph_count)448 hb_face_set_glyph_count (hb_face_t *face,
449 unsigned int glyph_count)
450 {
451 if (hb_object_is_inert (face))
452 return;
453
454 face->num_glyphs = glyph_count;
455 }
456
457 /**
458 * hb_face_get_glyph_count:
459 * @face: a face.
460 *
461 *
462 *
463 * Return value:
464 *
465 * Since: 1.0
466 **/
467 unsigned int
hb_face_get_glyph_count(hb_face_t * face)468 hb_face_get_glyph_count (hb_face_t *face)
469 {
470 return face->get_num_glyphs ();
471 }
472
473 void
load_num_glyphs(void) const474 hb_face_t::load_num_glyphs (void) const
475 {
476 hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>::sanitize (reference_table (HB_OT_TAG_maxp));
477 const OT::maxp *maxp_table = OT::Sanitizer<OT::maxp>::lock_instance (maxp_blob);
478 num_glyphs = maxp_table->get_num_glyphs ();
479 hb_blob_destroy (maxp_blob);
480 }
481
482
483