blob: bba1ee3fa0cfb2cd0bbf6a0e8900c7519433bbe3 [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
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070029#include "hb.hh"
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040030
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070031#include "hb-face.hh"
32#include "hb-blob.hh"
33#include "hb-open-file.hh"
Behdad Esfahboda84309a2018-08-26 09:33:01 -070034#include "hb-ot-face.hh"
Behdad Esfahbod3a0b3a22018-08-26 15:11:24 -070035#include "hb-ot-cmap-table.hh"
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040036
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040037
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043038/**
Behdad Esfahbod55bae682018-09-24 10:43:06 -040039 * hb_face_count:
40 * @blob: a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043041 *
Behdad Esfahbod55bae682018-09-24 10:43:06 -040042 * Get number of faces in a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043043 *
Behdad Esfahbod55bae682018-09-24 10:43:06 -040044 * Return value: Number of faces in @blob
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043045 *
Behdad Esfahboddf01f3e2018-06-05 15:17:39 -070046 * Since: 1.7.7
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043047 **/
48unsigned int
49hb_face_count (hb_blob_t *blob)
50{
51 if (unlikely (!blob))
52 return 0;
53
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020054 /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -070055 /* Make API signature const after. */
Behdad Esfahboded7b2e52018-08-01 23:59:09 -070056 hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
Ebrahim Byagowi8220ef82018-06-05 22:50:53 +043057 const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020058 unsigned int ret = ot.get_face_count ();
59 hb_blob_destroy (sanitized);
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043060
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020061 return ret;
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043062}
63
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040064/*
65 * hb_face_t
66 */
67
Behdad Esfahbod35066722018-08-06 06:17:48 -070068DEFINE_NULL_INSTANCE (hb_face_t) =
69{
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040070 HB_OBJECT_HEADER_STATIC,
71
72 true, /* immutable */
73
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020074 nullptr, /* reference_table_func */
75 nullptr, /* user_data */
76 nullptr, /* destroy */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040077
78 0, /* index */
79 1000, /* upem */
80 0, /* num_glyphs */
81
82 {
Behdad Esfahbod1f738092018-08-09 00:22:37 -070083#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040084#include "hb-shaper-list.hh"
85#undef HB_SHAPER_IMPLEMENT
86 },
87
Behdad Esfahbod1f738092018-08-09 00:22:37 -070088 HB_ATOMIC_PTR_INIT (nullptr), /* shape_plans */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040089};
90
91
Behdad Esfahbod288f2892013-09-06 15:40:22 -040092/**
93 * hb_face_create_for_tables:
Behdad Esfahbodace5c7e2013-09-13 20:34:42 -040094 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified):
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043095 * @user_data:
96 * @destroy:
Behdad Esfahbod288f2892013-09-06 15:40:22 -040097 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043098 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -040099 *
100 * Return value: (transfer full)
101 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430102 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400103 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400104hb_face_t *
105hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
106 void *user_data,
107 hb_destroy_func_t destroy)
108{
109 hb_face_t *face;
110
111 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
112 if (destroy)
113 destroy (user_data);
114 return hb_face_get_empty ();
115 }
116
117 face->reference_table_func = reference_table_func;
118 face->user_data = user_data;
119 face->destroy = destroy;
120
121 face->upem = 0;
122 face->num_glyphs = (unsigned int) -1;
123
124 return face;
125}
126
127
128typedef struct hb_face_for_data_closure_t {
129 hb_blob_t *blob;
130 unsigned int index;
131} hb_face_for_data_closure_t;
132
133static hb_face_for_data_closure_t *
134_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
135{
136 hb_face_for_data_closure_t *closure;
137
Behdad Esfahboda5efaac2015-10-02 08:02:29 +0100138 closure = (hb_face_for_data_closure_t *) calloc (1, sizeof (hb_face_for_data_closure_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400139 if (unlikely (!closure))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200140 return nullptr;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400141
142 closure->blob = blob;
143 closure->index = index;
144
145 return closure;
146}
147
148static void
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200149_hb_face_for_data_closure_destroy (void *data)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400150{
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200151 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
152
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400153 hb_blob_destroy (closure->blob);
154 free (closure);
155}
156
157static hb_blob_t *
158_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
159{
160 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
161
162 if (tag == HB_TAG_NONE)
163 return hb_blob_reference (data->blob);
164
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700165 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200166 unsigned int base_offset;
167 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400168
169 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
170
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200171 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400172
173 return blob;
174}
175
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400176/**
Behdad Esfahbod085d4292013-09-12 17:14:33 -0400177 * hb_face_create: (Xconstructor)
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430178 * @blob:
179 * @index:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400180 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430181 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400182 *
183 * Return value: (transfer full):
184 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430185 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400186 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400187hb_face_t *
188hb_face_create (hb_blob_t *blob,
189 unsigned int index)
190{
191 hb_face_t *face;
192
Behdad Esfahbodeb0bf3a2014-08-06 15:36:41 -0400193 if (unlikely (!blob))
194 blob = hb_blob_get_empty ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400195
Behdad Esfahboded7b2e52018-08-01 23:59:09 -0700196 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400197
198 if (unlikely (!closure))
199 return hb_face_get_empty ();
200
201 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
202 closure,
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200203 _hb_face_for_data_closure_destroy);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400204
Behdad Esfahbodd3d36912017-02-03 15:42:03 -0800205 face->index = index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400206
207 return face;
208}
209
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400210/**
211 * hb_face_get_empty:
212 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430213 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400214 *
215 * Return value: (transfer full)
216 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430217 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400218 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400219hb_face_t *
220hb_face_get_empty (void)
221{
Behdad Esfahbod35066722018-08-06 06:17:48 -0700222 return const_cast<hb_face_t *> (&Null(hb_face_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400223}
224
225
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400226/**
227 * hb_face_reference: (skip)
228 * @face: a face.
229 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400230 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430231 *
232 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400233 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430234 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400235 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400236hb_face_t *
237hb_face_reference (hb_face_t *face)
238{
239 return hb_object_reference (face);
240}
241
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400242/**
243 * hb_face_destroy: (skip)
244 * @face: a face.
245 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430246 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400247 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430248 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400249 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400250void
251hb_face_destroy (hb_face_t *face)
252{
253 if (!hb_object_destroy (face)) return;
254
Behdad Esfahbod1f738092018-08-09 00:22:37 -0700255 for (hb_face_t::plan_node_t *node = face->shape_plans.get (); node; )
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400256 {
257 hb_face_t::plan_node_t *next = node->next;
258 hb_shape_plan_destroy (node->shape_plan);
259 free (node);
260 node = next;
261 }
262
263#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
264#include "hb-shaper-list.hh"
265#undef HB_SHAPER_IMPLEMENT
266
267 if (face->destroy)
268 face->destroy (face->user_data);
269
270 free (face);
271}
272
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400273/**
274 * hb_face_set_user_data: (skip)
275 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430276 * @key:
277 * @data:
278 * @destroy:
279 * @replace:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400280 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400281 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430282 *
283 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400284 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430285 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400286 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400287hb_bool_t
288hb_face_set_user_data (hb_face_t *face,
289 hb_user_data_key_t *key,
290 void * data,
291 hb_destroy_func_t destroy,
292 hb_bool_t replace)
293{
294 return hb_object_set_user_data (face, key, data, destroy, replace);
295}
296
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400297/**
298 * hb_face_get_user_data: (skip)
299 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430300 * @key:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400301 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430302 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400303 *
304 * Return value: (transfer none):
305 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430306 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400307 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400308void *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700309hb_face_get_user_data (const hb_face_t *face,
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400310 hb_user_data_key_t *key)
311{
312 return hb_object_get_user_data (face, key);
313}
314
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400315/**
316 * hb_face_make_immutable:
317 * @face: a face.
318 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430319 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400320 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430321 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400322 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400323void
324hb_face_make_immutable (hb_face_t *face)
325{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400326 if (unlikely (hb_object_is_inert (face)))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400327 return;
Behdad Esfahbod90a0f9f2018-09-26 15:03:07 -0400328 if (face->immutable)
329 return;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400330
331 face->immutable = true;
332}
333
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400334/**
335 * hb_face_is_immutable:
336 * @face: a face.
337 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400338 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430339 *
340 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400341 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430342 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400343 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400344hb_bool_t
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700345hb_face_is_immutable (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400346{
347 return face->immutable;
348}
349
350
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400351/**
352 * hb_face_reference_table:
353 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430354 * @tag:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400355 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430356 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400357 *
358 * Return value: (transfer full):
359 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430360 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400361 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400362hb_blob_t *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700363hb_face_reference_table (const hb_face_t *face,
364 hb_tag_t tag)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400365{
366 return face->reference_table (tag);
367}
368
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400369/**
370 * hb_face_reference_blob:
371 * @face: a face.
372 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430373 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400374 *
375 * Return value: (transfer full):
376 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200377 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400378 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400379hb_blob_t *
380hb_face_reference_blob (hb_face_t *face)
381{
382 return face->reference_table (HB_TAG_NONE);
383}
384
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400385/**
386 * hb_face_set_index:
387 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430388 * @index:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400389 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430390 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400391 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200392 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400393 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400394void
395hb_face_set_index (hb_face_t *face,
396 unsigned int index)
397{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400398 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400399 return;
400
401 face->index = index;
402}
403
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400404/**
405 * hb_face_get_index:
406 * @face: a face.
407 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400408 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430409 *
410 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400411 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200412 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400413 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400414unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700415hb_face_get_index (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400416{
417 return face->index;
418}
419
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400420/**
421 * hb_face_set_upem:
422 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430423 * @upem:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400424 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430425 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400426 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200427 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400428 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400429void
430hb_face_set_upem (hb_face_t *face,
431 unsigned int upem)
432{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400433 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400434 return;
435
436 face->upem = upem;
437}
438
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400439/**
440 * hb_face_get_upem:
441 * @face: a face.
442 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400443 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430444 *
445 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400446 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430447 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400448 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400449unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700450hb_face_get_upem (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400451{
452 return face->get_upem ();
453}
454
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400455/**
456 * hb_face_set_glyph_count:
457 * @face: a face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430458 * @glyph_count:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400459 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430460 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400461 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200462 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400463 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400464void
465hb_face_set_glyph_count (hb_face_t *face,
466 unsigned int glyph_count)
467{
Behdad Esfahbod3f310dc2014-07-22 16:26:27 -0400468 if (face->immutable)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400469 return;
470
471 face->num_glyphs = glyph_count;
472}
473
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400474/**
475 * hb_face_get_glyph_count:
476 * @face: a face.
477 *
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400478 *
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430479 *
480 * Return value:
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400481 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200482 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400483 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400484unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700485hb_face_get_glyph_count (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400486{
487 return face->get_num_glyphs ();
488}
489
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200490/**
491 * hb_face_get_table_tags:
492 * @face: a face.
Behdad Esfahbod55bae682018-09-24 10:43:06 -0400493 * @start_offset: index of first tag to return.
494 * @table_count: input length of @table_tags array, output number of items written.
495 * @table_tags: array to write tags into.
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200496 *
497 * Retrieves table tags for a face, if possible.
498 *
499 * Return value: total number of tables, or 0 if not possible to list.
500 *
501 * Since: 1.6.0
502 **/
503unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700504hb_face_get_table_tags (const hb_face_t *face,
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200505 unsigned int start_offset,
506 unsigned int *table_count, /* IN/OUT */
507 hb_tag_t *table_tags /* OUT */)
508{
prrace498e4372018-06-09 16:04:28 -0700509 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200510 {
511 if (table_count)
512 *table_count = 0;
513 return 0;
514 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400515
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200516 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
517
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700518 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200519 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
520
521 return ot_face.get_table_tags (start_offset, table_count, table_tags);
522}
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700523
524
525/*
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700526 * Character set.
527 */
528
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700529
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700530/**
531 * hb_face_collect_unicodes:
532 * @face: font face.
533 * @out: set to add Unicode characters covered by @face to.
534 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200535 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700536 */
537void
538hb_face_collect_unicodes (hb_face_t *face,
539 hb_set_t *out)
540{
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700541 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
Behdad Esfahboda2680682018-08-26 15:18:46 -0700542 hb_ot_face_data (face)->cmap->collect_unicodes (out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700543}
544
545/**
546 * hb_face_collect_variation_selectors:
547 * @face: font face.
548 * @out: set to add Variation Selector characters covered by @face to.
549 *
550 *
551 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200552 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700553 */
554void
555hb_face_collect_variation_selectors (hb_face_t *face,
556 hb_set_t *out)
557{
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700558 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
Behdad Esfahboda2680682018-08-26 15:18:46 -0700559 hb_ot_face_data (face)->cmap->collect_variation_selectors (out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700560}
561
562/**
563 * hb_face_collect_variation_unicodes:
564 * @face: font face.
565 * @out: set to add Unicode characters for @variation_selector covered by @face to.
566 *
567 *
568 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200569 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700570 */
571void
572hb_face_collect_variation_unicodes (hb_face_t *face,
573 hb_codepoint_t variation_selector,
574 hb_set_t *out)
575{
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700576 if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
Behdad Esfahboda2680682018-08-26 15:18:46 -0700577 hb_ot_face_data (face)->cmap->collect_variation_unicodes (variation_selector, out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700578}
579
580
581
582/*
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700583 * face-builder: A face that has add_table().
584 */
585
586struct hb_face_builder_data_t
587{
588 struct table_entry_t
589 {
590 inline int cmp (const hb_tag_t *t) const
591 {
592 if (*t < tag) return -1;
593 if (*t > tag) return -1;
594 return 0;
595 }
596
597 hb_tag_t tag;
598 hb_blob_t *blob;
599 };
600
601 hb_vector_t<table_entry_t, 32> tables;
602};
603
604static hb_face_builder_data_t *
605_hb_face_builder_data_create (void)
606{
607 hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
608 if (unlikely (!data))
609 return nullptr;
610
611 data->tables.init ();
612
613 return data;
614}
615
616static void
617_hb_face_builder_data_destroy (void *user_data)
618{
619 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
620
621 for (unsigned int i = 0; i < data->tables.len; i++)
622 hb_blob_destroy (data->tables[i].blob);
623
624 data->tables.fini ();
625
626 free (data);
627}
628
629static hb_blob_t *
630_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
631{
632
633 unsigned int table_count = data->tables.len;
634 unsigned int face_length = table_count * 16 + 12;
635
636 for (unsigned int i = 0; i < table_count; i++)
Michiharu Ariza55942ad2018-10-06 14:49:44 -0700637 face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700638
639 char *buf = (char *) malloc (face_length);
640 if (unlikely (!buf))
641 return nullptr;
642
643 hb_serialize_context_t c (buf, face_length);
644 OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
645
646 bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
647 hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
648
649 Supplier<hb_tag_t> tags_supplier (&data->tables[0].tag, table_count, sizeof (data->tables[0]));
650 Supplier<hb_blob_t *> blobs_supplier (&data->tables[0].blob, table_count, sizeof (data->tables[0]));
651 bool ret = f->serialize_single (&c,
652 sfnt_tag,
653 tags_supplier,
654 blobs_supplier,
655 table_count);
656
657 c.end_serialize ();
658
659 if (unlikely (!ret))
660 {
661 free (buf);
662 return nullptr;
663 }
664
665 return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
666}
667
668static hb_blob_t *
669_hb_face_builder_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
670{
671 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
672
673 if (!tag)
674 return _hb_face_builder_data_reference_blob (data);
675
676 hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
677 if (entry)
678 return hb_blob_reference (entry->blob);
679
680 return nullptr;
681}
682
683
684/**
685 * hb_face_builder_create:
686 *
687 * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
688 * After tables are added to the face, it can be compiled to a binary
689 * font file by calling hb_face_reference_blob().
690 *
HinTakbd1be872018-10-03 07:11:22 +0800691 * Return value: (transfer full): New face.
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700692 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200693 * Since: 1.9.0
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700694 **/
695hb_face_t *
696hb_face_builder_create (void)
697{
698 hb_face_builder_data_t *data = _hb_face_builder_data_create ();
699 if (unlikely (!data)) return hb_face_get_empty ();
700
701 return hb_face_create_for_tables (_hb_face_builder_reference_table,
702 data,
703 _hb_face_builder_data_destroy);
704}
705
706/**
707 * hb_face_builder_add_table:
708 *
709 * Add table for @tag with data provided by @blob to the face. @face must
710 * be created using hb_face_builder_create().
711 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200712 * Since: 1.9.0
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700713 **/
714hb_bool_t
715hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
716{
717 if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
718 return false;
719
720 hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
721 hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
722
723 entry->tag = tag;
724 entry->blob = hb_blob_reference (blob);
725
726 return true;
727}