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