blob: 2c0087370c2651cb18aa169980e8bb2cb3932cf8 [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"
Garret Riegerdea0fe52021-08-04 16:36:20 -070036#include "hb-map.hh"
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040037
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040038
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043039/**
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070040 * SECTION:hb-face
Behdad Esfahbodcf5fa572018-10-27 04:50:38 -070041 * @title: hb-face
Behdad Esfahbod5dd86aa2018-10-27 04:28:40 -070042 * @short_description: Font face objects
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070043 * @include: hb.h
44 *
Nathan Willis3e72feb2019-04-22 19:21:27 +010045 * A font face is an object that represents a single face from within a
46 * font family.
47 *
48 * More precisely, a font face represents a single face in a binary font file.
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070049 * Font faces are typically built from a binary blob and a face index.
50 * Font faces are used to create fonts.
51 **/
52
53
54/**
Behdad Esfahbod55bae682018-09-24 10:43:06 -040055 * hb_face_count:
56 * @blob: a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043057 *
Nathan Willis3e72feb2019-04-22 19:21:27 +010058 * Fetches the number of faces in a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043059 *
Behdad Esfahbod55bae682018-09-24 10:43:06 -040060 * Return value: Number of faces in @blob
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043061 *
Behdad Esfahboddf01f3e2018-06-05 15:17:39 -070062 * Since: 1.7.7
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043063 **/
64unsigned int
65hb_face_count (hb_blob_t *blob)
66{
67 if (unlikely (!blob))
68 return 0;
69
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020070 /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -070071 /* Make API signature const after. */
Behdad Esfahboded7b2e52018-08-01 23:59:09 -070072 hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
Ebrahim Byagowi8220ef82018-06-05 22:50:53 +043073 const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020074 unsigned int ret = ot.get_face_count ();
75 hb_blob_destroy (sanitized);
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043076
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020077 return ret;
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043078}
79
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040080/*
81 * hb_face_t
82 */
83
Behdad Esfahbod35066722018-08-06 06:17:48 -070084DEFINE_NULL_INSTANCE (hb_face_t) =
85{
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040086 HB_OBJECT_HEADER_STATIC,
87
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020088 nullptr, /* reference_table_func */
89 nullptr, /* user_data */
90 nullptr, /* destroy */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040091
92 0, /* index */
Behdad Esfahbod140797d2020-06-29 03:51:09 -070093 1000, /* upem */
94 0, /* num_glyphs */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040095
Behdad Esfahbode88d47b2018-11-11 16:25:43 -050096 /* Zero for the rest is fine. */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040097};
98
99
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400100/**
101 * hb_face_create_for_tables:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100102 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function
103 * @user_data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200104 * @destroy: (nullable): A callback to call when @data is not needed anymore
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400105 *
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200106 * Variant of hb_face_create(), built for those cases where it is more
107 * convenient to provide data for individual tables instead of the whole font
108 * data. With the caveat that hb_face_get_table_tags() does not currently work
109 * with faces created this way.
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200110 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100111 * Creates a new face object from the specified @user_data and @reference_table_func,
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200112 * with the @destroy callback.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400113 *
n8willis41b46a32020-04-26 16:01:31 +0100114 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400115 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430116 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400117 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400118hb_face_t *
119hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
120 void *user_data,
121 hb_destroy_func_t destroy)
122{
123 hb_face_t *face;
124
125 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
126 if (destroy)
127 destroy (user_data);
128 return hb_face_get_empty ();
129 }
130
131 face->reference_table_func = reference_table_func;
132 face->user_data = user_data;
133 face->destroy = destroy;
134
Behdad Esfahbodfc44dea2018-11-13 11:54:33 -0500135 face->num_glyphs.set_relaxed (-1);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400136
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500137 face->data.init0 (face);
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500138 face->table.init0 (face);
139
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400140 return face;
141}
142
143
144typedef struct hb_face_for_data_closure_t {
145 hb_blob_t *blob;
146 unsigned int index;
147} hb_face_for_data_closure_t;
148
149static hb_face_for_data_closure_t *
150_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
151{
152 hb_face_for_data_closure_t *closure;
153
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600154 closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400155 if (unlikely (!closure))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200156 return nullptr;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400157
158 closure->blob = blob;
159 closure->index = index;
160
161 return closure;
162}
163
164static void
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200165_hb_face_for_data_closure_destroy (void *data)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400166{
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200167 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
168
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400169 hb_blob_destroy (closure->blob);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600170 hb_free (closure);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400171}
172
173static hb_blob_t *
174_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
175{
176 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
177
178 if (tag == HB_TAG_NONE)
179 return hb_blob_reference (data->blob);
180
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700181 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200182 unsigned int base_offset;
183 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400184
185 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
186
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200187 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400188
189 return blob;
190}
191
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400192/**
Behdad Esfahbod085d4292013-09-12 17:14:33 -0400193 * hb_face_create: (Xconstructor)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100194 * @blob: #hb_blob_t to work upon
195 * @index: The index of the face within @blob
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400196 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100197 * Constructs a new face object from the specified blob and
n8willis726e3202020-04-26 15:56:57 +0100198 * a face index into that blob. This is used for blobs of
199 * file formats such as Dfont and TTC that can contain more
200 * than one face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430201 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100202 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400203 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430204 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400205 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400206hb_face_t *
207hb_face_create (hb_blob_t *blob,
208 unsigned int index)
209{
210 hb_face_t *face;
211
Behdad Esfahbodeb0bf3a2014-08-06 15:36:41 -0400212 if (unlikely (!blob))
213 blob = hb_blob_get_empty ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400214
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800215 blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
216
217 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (blob, index);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400218
219 if (unlikely (!closure))
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800220 {
221 hb_blob_destroy (blob);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400222 return hb_face_get_empty ();
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800223 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400224
225 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
226 closure,
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200227 _hb_face_for_data_closure_destroy);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400228
Behdad Esfahbodd3d36912017-02-03 15:42:03 -0800229 face->index = index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400230
231 return face;
232}
233
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400234/**
235 * hb_face_get_empty:
236 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100237 * Fetches the singleton empty face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430238 *
Khaled Hosny3d7a3612020-12-30 23:58:37 +0200239 * Return value: (transfer full): The empty face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400240 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430241 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400242 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400243hb_face_t *
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330244hb_face_get_empty ()
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400245{
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430246 return const_cast<hb_face_t *> (&Null (hb_face_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400247}
248
249
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400250/**
251 * hb_face_reference: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100252 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400253 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100254 * Increases the reference count on a face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400255 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100256 * Return value: The @face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400257 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430258 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400259 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400260hb_face_t *
261hb_face_reference (hb_face_t *face)
262{
263 return hb_object_reference (face);
264}
265
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400266/**
267 * hb_face_destroy: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100268 * @face: A face object
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200269 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100270 * Decreases the reference count on a face object. When the
271 * reference count reaches zero, the face is destroyed,
272 * freeing all memory.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400273 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430274 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400275 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400276void
277hb_face_destroy (hb_face_t *face)
278{
279 if (!hb_object_destroy (face)) return;
280
Behdad Esfahbodf6fc5572018-11-05 13:23:54 -0500281 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400282 {
283 hb_face_t::plan_node_t *next = node->next;
284 hb_shape_plan_destroy (node->shape_plan);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600285 hb_free (node);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400286 node = next;
287 }
288
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500289 face->data.fini ();
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500290 face->table.fini ();
291
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400292 if (face->destroy)
293 face->destroy (face->user_data);
294
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600295 hb_free (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400296}
297
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400298/**
299 * hb_face_set_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100300 * @face: A face object
301 * @key: The user-data key to set
302 * @data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200303 * @destroy: (nullable): A callback to call when @data is not needed anymore
Nathan Willis3e72feb2019-04-22 19:21:27 +0100304 * @replace: Whether to replace an existing data with the same key
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400305 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200306 * Attaches a user-data key/data pair to the given face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400307 *
Khaled Hosnyf88e8452020-12-24 21:28:37 +0200308 * Return value: %true if success, %false otherwise
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400309 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430310 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400311 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400312hb_bool_t
313hb_face_set_user_data (hb_face_t *face,
314 hb_user_data_key_t *key,
315 void * data,
316 hb_destroy_func_t destroy,
317 hb_bool_t replace)
318{
319 return hb_object_set_user_data (face, key, data, destroy, replace);
320}
321
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400322/**
323 * hb_face_get_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100324 * @face: A face object
325 * @key: The user-data key to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400326 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100327 * Fetches the user data associated with the specified key,
328 * attached to the specified face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430329 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100330 * Return value: (transfer none): A pointer to the user data
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400331 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430332 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400333 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400334void *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700335hb_face_get_user_data (const hb_face_t *face,
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400336 hb_user_data_key_t *key)
337{
338 return hb_object_get_user_data (face, key);
339}
340
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400341/**
342 * hb_face_make_immutable:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100343 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400344 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100345 * Makes the given face object immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400346 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430347 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400348 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400349void
350hb_face_make_immutable (hb_face_t *face)
351{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400352 if (hb_object_is_immutable (face))
Behdad Esfahbod90a0f9f2018-09-26 15:03:07 -0400353 return;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400354
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400355 hb_object_make_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400356}
357
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400358/**
359 * hb_face_is_immutable:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100360 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400361 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100362 * Tests whether the given face object is immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400363 *
Khaled Hosnya8e72ee2020-12-30 23:08:40 +0200364 * Return value: %true is @face is immutable, %false otherwise
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400365 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430366 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400367 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400368hb_bool_t
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700369hb_face_is_immutable (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400370{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400371 return hb_object_is_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400372}
373
374
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400375/**
376 * hb_face_reference_table:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100377 * @face: A face object
378 * @tag: The #hb_tag_t of the table to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400379 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100380 * Fetches a reference to the specified table within
381 * the specified face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430382 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100383 * Return value: (transfer full): A pointer to the @tag table within @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400384 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430385 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400386 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400387hb_blob_t *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700388hb_face_reference_table (const hb_face_t *face,
389 hb_tag_t tag)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400390{
Ebrahim Byagowif441a7c2019-09-01 02:18:09 +0430391 if (unlikely (tag == HB_TAG_NONE))
392 return hb_blob_get_empty ();
393
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400394 return face->reference_table (tag);
395}
396
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400397/**
398 * hb_face_reference_blob:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100399 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400400 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100401 * Fetches a pointer to the binary blob that contains the
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200402 * specified face. Returns an empty blob if referencing face data is not
403 * possible.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430404 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100405 * Return value: (transfer full): A pointer to the blob for @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400406 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200407 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400408 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400409hb_blob_t *
410hb_face_reference_blob (hb_face_t *face)
411{
412 return face->reference_table (HB_TAG_NONE);
413}
414
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400415/**
416 * hb_face_set_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100417 * @face: A face object
418 * @index: The index to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400419 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100420 * Assigns the specified face-index to @face. Fails if the
421 * face is immutable.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430422 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100423 * <note>Note: face indices within a collection are zero-based.</note>
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400424 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200425 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400426 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400427void
428hb_face_set_index (hb_face_t *face,
429 unsigned int index)
430{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400431 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400432 return;
433
434 face->index = index;
435}
436
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400437/**
438 * hb_face_get_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100439 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400440 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100441 * Fetches the face-index corresponding to the given face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400442 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100443 * <note>Note: face indices within a collection are zero-based.</note>
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430444 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200445 * Return value: The index of @face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400446 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200447 * 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_index (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400451{
452 return face->index;
453}
454
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400455/**
456 * hb_face_set_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100457 * @face: A face object
458 * @upem: The units-per-em value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400459 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100460 * Sets the units-per-em (upem) for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400461 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200462 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400463 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400464void
465hb_face_set_upem (hb_face_t *face,
466 unsigned int upem)
467{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400468 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400469 return;
470
Behdad Esfahbodfc44dea2018-11-13 11:54:33 -0500471 face->upem.set_relaxed (upem);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400472}
473
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400474/**
475 * hb_face_get_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100476 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400477 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100478 * Fetches the units-per-em (upem) value of the specified face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400479 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100480 * Return value: The upem value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400481 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430482 * Since: 0.9.2
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_upem (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400486{
487 return face->get_upem ();
488}
489
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400490/**
491 * hb_face_set_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100492 * @face: A face object
493 * @glyph_count: The glyph-count value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400494 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100495 * Sets the glyph count for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400496 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200497 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400498 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400499void
500hb_face_set_glyph_count (hb_face_t *face,
501 unsigned int glyph_count)
502{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400503 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400504 return;
505
Behdad Esfahbodfc44dea2018-11-13 11:54:33 -0500506 face->num_glyphs.set_relaxed (glyph_count);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400507}
508
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400509/**
510 * hb_face_get_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100511 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400512 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100513 * Fetches the glyph-count value of the specified face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400514 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100515 * Return value: The glyph-count value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400516 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200517 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400518 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400519unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700520hb_face_get_glyph_count (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400521{
522 return face->get_num_glyphs ();
523}
524
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200525/**
526 * hb_face_get_table_tags:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100527 * @face: A face object
528 * @start_offset: The index of first table tag to retrieve
529 * @table_count: (inout): Input = the maximum number of table tags to return;
530 * Output = the actual number of table tags returned (may be zero)
531 * @table_tags: (out) (array length=table_count): The array of table tags found
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200532 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100533 * Fetches a list of all table tags for a face, if possible. The list returned will
534 * begin at the offset provided
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200535 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100536 * Return value: Total number of tables, or zero if it is not possible to list
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200537 *
538 * Since: 1.6.0
539 **/
540unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700541hb_face_get_table_tags (const hb_face_t *face,
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200542 unsigned int start_offset,
543 unsigned int *table_count, /* IN/OUT */
544 hb_tag_t *table_tags /* OUT */)
545{
prrace498e4372018-06-09 16:04:28 -0700546 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200547 {
548 if (table_count)
549 *table_count = 0;
550 return 0;
551 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400552
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200553 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
554
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700555 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200556 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
557
558 return ot_face.get_table_tags (start_offset, table_count, table_tags);
559}
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700560
561
562/*
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700563 * Character set.
564 */
565
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700566
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700567#ifndef HB_NO_FACE_COLLECT_UNICODES
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700568/**
569 * hb_face_collect_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100570 * @face: A face object
571 * @out: The set to add Unicode characters to
572 *
573 * Collects all of the Unicode characters covered by @face and adds
574 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700575 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200576 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700577 */
578void
579hb_face_collect_unicodes (hb_face_t *face,
580 hb_set_t *out)
581{
Michiharu Ariza5ab50ee2020-02-29 01:32:29 -0800582 face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700583}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700584/**
585 * hb_face_collect_variation_selectors:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100586 * @face: A face object
587 * @out: The set to add Variation Selector characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700588 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100589 * Collects all Unicode "Variation Selector" characters covered by @face and adds
590 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700591 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200592 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700593 */
594void
595hb_face_collect_variation_selectors (hb_face_t *face,
596 hb_set_t *out)
597{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500598 face->table.cmap->collect_variation_selectors (out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700599}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700600/**
601 * hb_face_collect_variation_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100602 * @face: A face object
603 * @variation_selector: The Variation Selector to query
604 * @out: The set to add Unicode characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700605 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100606 * Collects all Unicode characters for @variation_selector covered by @face and adds
607 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700608 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200609 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700610 */
611void
612hb_face_collect_variation_unicodes (hb_face_t *face,
613 hb_codepoint_t variation_selector,
614 hb_set_t *out)
615{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500616 face->table.cmap->collect_variation_unicodes (variation_selector, out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700617}
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700618#endif
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700619
620
621/*
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700622 * face-builder: A face that has add_table().
623 */
624
625struct hb_face_builder_data_t
626{
Behdad Esfahbod2cb8c922021-08-05 12:27:22 -0600627 hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700628};
629
Behdad Esfahbod74ad5dd2021-08-05 11:51:54 -0600630static int compare_entries (const void* pa, const void* pb)
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700631{
Behdad Esfahbod74ad5dd2021-08-05 11:51:54 -0600632 const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
633 const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700634
Behdad Esfahbod74ad5dd2021-08-05 11:51:54 -0600635 /* Order by blob size first (smallest to largest) and then table tag */
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700636
Behdad Esfahbod74ad5dd2021-08-05 11:51:54 -0600637 if (a.second->length != b.second->length)
638 return a.second->length < b.second->length ? -1 : +1;
639
640 return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700641}
642
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700643static hb_face_builder_data_t *
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330644_hb_face_builder_data_create ()
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700645{
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600646 hb_face_builder_data_t *data = (hb_face_builder_data_t *) hb_calloc (1, sizeof (hb_face_builder_data_t));
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700647 if (unlikely (!data))
648 return nullptr;
649
650 data->tables.init ();
651
652 return data;
653}
654
655static void
656_hb_face_builder_data_destroy (void *user_data)
657{
658 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
659
Garret Riegerdea0fe52021-08-04 16:36:20 -0700660 for (hb_blob_t* b : data->tables.values())
661 hb_blob_destroy (b);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700662
663 data->tables.fini ();
664
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600665 hb_free (data);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700666}
667
668static hb_blob_t *
669_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
670{
671
Garret Riegerdea0fe52021-08-04 16:36:20 -0700672 unsigned int table_count = data->tables.get_population ();
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700673 unsigned int face_length = table_count * 16 + 12;
674
Garret Riegerdea0fe52021-08-04 16:36:20 -0700675 for (hb_blob_t* b : data->tables.values())
676 face_length += hb_ceil_to_4 (hb_blob_get_length (b));
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700677
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600678 char *buf = (char *) hb_malloc (face_length);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700679 if (unlikely (!buf))
680 return nullptr;
681
682 hb_serialize_context_t c (buf, face_length);
Behdad Esfahbodf9417af2018-12-18 13:23:32 -0500683 c.propagate_error (data->tables);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700684 OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
685
Garret Riegerdea0fe52021-08-04 16:36:20 -0700686 bool is_cff = (data->tables.has (HB_TAG ('C','F','F',' '))
687 || data->tables.has (HB_TAG ('C','F','F','2')));
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700688 hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
689
Garret Riegerdea0fe52021-08-04 16:36:20 -0700690 // Sort the tags so that produced face is deterministic.
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700691 hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
692 data->tables.iter () | hb_sink (sorted_entries);
Garret Rieger8c0c2172021-08-06 10:45:38 -0700693 if (unlikely (sorted_entries.in_error ()))
694 {
695 hb_free (buf);
696 return nullptr;
697 }
698
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700699 sorted_entries.qsort (compare_entries);
700 bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700701
702 c.end_serialize ();
703
704 if (unlikely (!ret))
705 {
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600706 hb_free (buf);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700707 return nullptr;
708 }
709
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600710 return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, hb_free);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700711}
712
713static hb_blob_t *
Behdad Esfahbod39bd07a2018-10-26 21:01:11 -0700714_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700715{
716 hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
717
718 if (!tag)
719 return _hb_face_builder_data_reference_blob (data);
720
Garret Riegerc2ee1fd2021-08-04 16:42:49 -0700721 return hb_blob_reference (data->tables[tag]);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700722}
723
724
725/**
726 * hb_face_builder_create:
727 *
728 * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
729 * After tables are added to the face, it can be compiled to a binary
730 * font file by calling hb_face_reference_blob().
731 *
HinTakbd1be872018-10-03 07:11:22 +0800732 * Return value: (transfer full): New face.
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700733 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200734 * Since: 1.9.0
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700735 **/
736hb_face_t *
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330737hb_face_builder_create ()
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700738{
739 hb_face_builder_data_t *data = _hb_face_builder_data_create ();
740 if (unlikely (!data)) return hb_face_get_empty ();
741
742 return hb_face_create_for_tables (_hb_face_builder_reference_table,
743 data,
744 _hb_face_builder_data_destroy);
745}
746
747/**
748 * hb_face_builder_add_table:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100749 * @face: A face object created with hb_face_builder_create()
750 * @tag: The #hb_tag_t of the table to add
751 * @blob: The blob containing the table data to add
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700752 *
753 * Add table for @tag with data provided by @blob to the face. @face must
754 * be created using hb_face_builder_create().
755 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200756 * Since: 1.9.0
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700757 **/
758hb_bool_t
759hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
760{
Garret Riegere5bfd492021-08-05 14:03:25 -0700761 if (tag == HB_MAP_VALUE_INVALID)
762 return false;
763
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700764 if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
765 return false;
766
767 hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
Garret Riegerdae32b42020-07-28 18:31:46 -0700768
Garret Rieger222b74f2021-08-05 11:39:26 -0700769 hb_blob_t* previous = data->tables.get (tag);
Garret Riegerdea0fe52021-08-04 16:36:20 -0700770 if (!data->tables.set (tag, hb_blob_reference (blob)))
771 {
772 hb_blob_destroy (blob);
Garret Riegerdae32b42020-07-28 18:31:46 -0700773 return false;
Garret Riegerdea0fe52021-08-04 16:36:20 -0700774 }
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700775
Garret Rieger222b74f2021-08-05 11:39:26 -0700776 hb_blob_destroy (previous);
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700777 return true;
778}