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