blob: 01271413e62351a5a25645f3273a1649ea9b52f2 [file] [log] [blame]
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -04001/*
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
Behdad Esfahbod113393e2017-01-21 15:12:03 -080031#include "hb-face-private.hh"
Behdad Esfahbodb4fa5052018-05-08 02:45:08 -070032#include "hb-blob-private.hh"
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040033#include "hb-open-file-private.hh"
34#include "hb-ot-head-table.hh"
35#include "hb-ot-maxp-table.hh"
36
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040037
38/*
39 * hb_face_t
40 */
41
42const hb_face_t _hb_face_nil = {
43 HB_OBJECT_HEADER_STATIC,
44
45 true, /* immutable */
46
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020047 nullptr, /* reference_table_func */
48 nullptr, /* user_data */
49 nullptr, /* destroy */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040050
51 0, /* index */
52 1000, /* upem */
53 0, /* num_glyphs */
54
55 {
56#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
57#include "hb-shaper-list.hh"
58#undef HB_SHAPER_IMPLEMENT
59 },
60
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020061 nullptr, /* shape_plans */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040062};
63
64
Behdad Esfahbod288f2892013-09-06 15:40:22 -040065/**
66 * hb_face_create_for_tables:
Behdad Esfahbodace5c7e2013-09-13 20:34:42 -040067 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
Behdad Esfahbod288f2892013-09-06 15:40:22 -040068 * @user_data:
69 * @destroy:
70 *
71 *
72 *
73 * Return value: (transfer full)
74 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +043075 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -040076 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040077hb_face_t *
78hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
79 void *user_data,
80 hb_destroy_func_t destroy)
81{
82 hb_face_t *face;
83
84 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
85 if (destroy)
86 destroy (user_data);
87 return hb_face_get_empty ();
88 }
89
90 face->reference_table_func = reference_table_func;
91 face->user_data = user_data;
92 face->destroy = destroy;
93
94 face->upem = 0;
95 face->num_glyphs = (unsigned int) -1;
96
97 return face;
98}
99
100
101typedef struct hb_face_for_data_closure_t {
102 hb_blob_t *blob;
103 unsigned int index;
104} hb_face_for_data_closure_t;
105
106static hb_face_for_data_closure_t *
107_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
108{
109 hb_face_for_data_closure_t *closure;
110
Behdad Esfahboda5efaac2015-10-02 08:02:29 +0100111 closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400112 if (unlikely (!closure))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200113 return nullptr;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400114
115 closure->blob = blob;
116 closure->index = index;
117
118 return closure;
119}
120
121static void
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200122_hb_face_for_data_closure_destroy (void *data)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400123{
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200124 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
125
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400126 hb_blob_destroy (closure->blob);
127 free (closure);
128}
129
130static hb_blob_t *
131_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
132{
133 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
134
135 if (tag == HB_TAG_NONE)
136 return hb_blob_reference (data->blob);
137
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700138 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400139 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
140
141 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
142
143 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
144
145 return blob;
146}
147
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400148/**
Behdad Esfahbod085d4292013-09-12 17:14:33 -0400149 * hb_face_create: (Xconstructor)
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400150 * @blob:
151 * @index:
152 *
153 *
154 *
155 * Return value: (transfer full):
156 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430157 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400158 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400159hb_face_t *
160hb_face_create (hb_blob_t *blob,
161 unsigned int index)
162{
163 hb_face_t *face;
164
Behdad Esfahbodeb0bf3a2014-08-06 15:36:41 -0400165 if (unlikely (!blob))
166 blob = hb_blob_get_empty ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400167
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100168 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400169
170 if (unlikely (!closure))
171 return hb_face_get_empty ();
172
173 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
174 closure,
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200175 _hb_face_for_data_closure_destroy);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400176
Behdad Esfahbodd3d36912017-02-03 15:42:03 -0800177 face->index = index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400178
179 return face;
180}
181
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400182/**
183 * hb_face_get_empty:
184 *
185 *
186 *
187 * Return value: (transfer full)
188 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430189 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400190 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400191hb_face_t *
192hb_face_get_empty (void)
193{
194 return const_cast<hb_face_t *> (&_hb_face_nil);
195}
196
197
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400198/**
199 * hb_face_reference: (skip)
200 * @face: a face.
201 *
202 *
203 *
204 * Return value:
205 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430206 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400207 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400208hb_face_t *
209hb_face_reference (hb_face_t *face)
210{
211 return hb_object_reference (face);
212}
213
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400214/**
215 * hb_face_destroy: (skip)
216 * @face: a face.
217 *
218 *
219 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430220 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400221 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400222void
223hb_face_destroy (hb_face_t *face)
224{
225 if (!hb_object_destroy (face)) return;
226
227 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
228 {
229 hb_face_t::plan_node_t *next = node->next;
230 hb_shape_plan_destroy (node->shape_plan);
231 free (node);
232 node = next;
233 }
234
235#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
236#include "hb-shaper-list.hh"
237#undef HB_SHAPER_IMPLEMENT
238
239 if (face->destroy)
240 face->destroy (face->user_data);
241
242 free (face);
243}
244
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400245/**
246 * hb_face_set_user_data: (skip)
247 * @face: a face.
248 * @key:
249 * @data:
250 * @destroy:
251 * @replace:
252 *
253 *
254 *
255 * Return value:
256 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430257 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400258 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400259hb_bool_t
260hb_face_set_user_data (hb_face_t *face,
261 hb_user_data_key_t *key,
262 void * data,
263 hb_destroy_func_t destroy,
264 hb_bool_t replace)
265{
266 return hb_object_set_user_data (face, key, data, destroy, replace);
267}
268
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400269/**
270 * hb_face_get_user_data: (skip)
271 * @face: a face.
272 * @key:
273 *
274 *
275 *
276 * Return value: (transfer none):
277 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430278 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400279 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400280void *
281hb_face_get_user_data (hb_face_t *face,
282 hb_user_data_key_t *key)
283{
284 return hb_object_get_user_data (face, key);
285}
286
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400287/**
288 * hb_face_make_immutable:
289 * @face: a face.
290 *
291 *
292 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430293 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400294 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400295void
296hb_face_make_immutable (hb_face_t *face)
297{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400298 if (unlikely (hb_object_is_inert (face)))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400299 return;
300
301 face->immutable = true;
302}
303
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400304/**
305 * hb_face_is_immutable:
306 * @face: a face.
307 *
308 *
309 *
310 * Return value:
311 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430312 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400313 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400314hb_bool_t
315hb_face_is_immutable (hb_face_t *face)
316{
317 return face->immutable;
318}
319
320
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400321/**
322 * hb_face_reference_table:
323 * @face: a face.
324 * @tag:
325 *
326 *
327 *
328 * Return value: (transfer full):
329 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430330 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400331 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400332hb_blob_t *
333hb_face_reference_table (hb_face_t *face,
334 hb_tag_t tag)
335{
336 return face->reference_table (tag);
337}
338
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400339/**
340 * hb_face_reference_blob:
341 * @face: a face.
342 *
343 *
344 *
345 * Return value: (transfer full):
346 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200347 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400348 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400349hb_blob_t *
350hb_face_reference_blob (hb_face_t *face)
351{
352 return face->reference_table (HB_TAG_NONE);
353}
354
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400355/**
356 * hb_face_set_index:
357 * @face: a face.
358 * @index:
359 *
360 *
361 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200362 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400363 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400364void
365hb_face_set_index (hb_face_t *face,
366 unsigned int index)
367{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400368 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400369 return;
370
371 face->index = index;
372}
373
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400374/**
375 * hb_face_get_index:
376 * @face: a face.
377 *
378 *
379 *
380 * Return value:
381 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200382 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400383 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400384unsigned int
385hb_face_get_index (hb_face_t *face)
386{
387 return face->index;
388}
389
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400390/**
391 * hb_face_set_upem:
392 * @face: a face.
393 * @upem:
394 *
395 *
396 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200397 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400398 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400399void
400hb_face_set_upem (hb_face_t *face,
401 unsigned int upem)
402{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400403 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400404 return;
405
406 face->upem = upem;
407}
408
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400409/**
410 * hb_face_get_upem:
411 * @face: a face.
412 *
413 *
414 *
415 * Return value:
416 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430417 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400418 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400419unsigned int
420hb_face_get_upem (hb_face_t *face)
421{
422 return face->get_upem ();
423}
424
425void
426hb_face_t::load_upem (void) const
427{
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100428 hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700429 const OT::head *head_table = head_blob->as<OT::head> ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400430 upem = head_table->get_upem ();
431 hb_blob_destroy (head_blob);
432}
433
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400434/**
435 * hb_face_set_glyph_count:
436 * @face: a face.
437 * @glyph_count:
438 *
439 *
440 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200441 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400442 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400443void
444hb_face_set_glyph_count (hb_face_t *face,
445 unsigned int glyph_count)
446{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400447 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400448 return;
449
450 face->num_glyphs = glyph_count;
451}
452
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400453/**
454 * hb_face_get_glyph_count:
455 * @face: a face.
456 *
457 *
458 *
459 * Return value:
460 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200461 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400462 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400463unsigned int
464hb_face_get_glyph_count (hb_face_t *face)
465{
466 return face->get_num_glyphs ();
467}
468
469void
470hb_face_t::load_num_glyphs (void) const
471{
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100472 hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700473 const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400474 num_glyphs = maxp_table->get_num_glyphs ();
475 hb_blob_destroy (maxp_blob);
476}
477
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200478/**
479 * hb_face_get_table_tags:
480 * @face: a face.
481 *
482 * Retrieves table tags for a face, if possible.
483 *
484 * Return value: total number of tables, or 0 if not possible to list.
485 *
486 * Since: 1.6.0
487 **/
488unsigned int
489hb_face_get_table_tags (hb_face_t *face,
490 unsigned int start_offset,
491 unsigned int *table_count, /* IN/OUT */
492 hb_tag_t *table_tags /* OUT */)
493{
494 if (face->destroy != _hb_face_for_data_closure_destroy)
495 {
496 if (table_count)
497 *table_count = 0;
498 return 0;
499 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400500
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200501 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
502
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700503 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200504 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
505
506 return ot_face.get_table_tags (start_offset, table_count, table_tags);
507}