blob: e340710586c15b7610af29da7a7fa272d86f9c27 [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 Esfahbod00cf4e52018-10-27 04:07:33 -070039 * SECTION:hb-face
Behdad Esfahbodcf5fa572018-10-27 04:50:38 -070040 * @title: hb-face
Behdad Esfahbod5dd86aa2018-10-27 04:28:40 -070041 * @short_description: Font face objects
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070042 * @include: hb.h
43 *
Nathan Willis3e72feb2019-04-22 19:21:27 +010044 * A font face is an object that represents a single face from within a
45 * font family.
46 *
47 * More precisely, a font face represents a single face in a binary font file.
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070048 * Font faces are typically built from a binary blob and a face index.
49 * Font faces are used to create fonts.
Behdad Esfahbod48f8ed72023-04-22 10:11:22 -060050 *
51 * A font face can be created from a binary blob using hb_face_create().
52 * The face index is used to select a face from a binary blob that contains
53 * multiple faces. For example, a binary blob that contains both a regular
54 * and a bold face can be used to create two font faces, one for each face
55 * index.
Behdad Esfahbod00cf4e52018-10-27 04:07:33 -070056 **/
57
58
59/**
Behdad Esfahbod55bae682018-09-24 10:43:06 -040060 * hb_face_count:
61 * @blob: a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043062 *
Nathan Willis3e72feb2019-04-22 19:21:27 +010063 * Fetches the number of faces in a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043064 *
Behdad Esfahbod55bae682018-09-24 10:43:06 -040065 * Return value: Number of faces in @blob
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043066 *
Behdad Esfahboddf01f3e2018-06-05 15:17:39 -070067 * Since: 1.7.7
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043068 **/
69unsigned int
70hb_face_count (hb_blob_t *blob)
71{
72 if (unlikely (!blob))
73 return 0;
74
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020075 /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -070076 /* Make API signature const after. */
Behdad Esfahboded7b2e52018-08-01 23:59:09 -070077 hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
Ebrahim Byagowi8220ef82018-06-05 22:50:53 +043078 const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020079 unsigned int ret = ot.get_face_count ();
80 hb_blob_destroy (sanitized);
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043081
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020082 return ret;
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043083}
84
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040085/*
86 * hb_face_t
87 */
88
Behdad Esfahbod35066722018-08-06 06:17:48 -070089DEFINE_NULL_INSTANCE (hb_face_t) =
90{
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040091 HB_OBJECT_HEADER_STATIC,
92
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020093 nullptr, /* reference_table_func */
94 nullptr, /* user_data */
95 nullptr, /* destroy */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040096
97 0, /* index */
Behdad Esfahbod140797d2020-06-29 03:51:09 -070098 1000, /* upem */
99 0, /* num_glyphs */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400100
Behdad Esfahbode88d47b2018-11-11 16:25:43 -0500101 /* Zero for the rest is fine. */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400102};
103
104
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400105/**
106 * hb_face_create_for_tables:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100107 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function
108 * @user_data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200109 * @destroy: (nullable): A callback to call when @data is not needed anymore
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400110 *
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200111 * Variant of hb_face_create(), built for those cases where it is more
112 * convenient to provide data for individual tables instead of the whole font
113 * data. With the caveat that hb_face_get_table_tags() does not currently work
114 * with faces created this way.
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200115 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100116 * Creates a new face object from the specified @user_data and @reference_table_func,
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200117 * with the @destroy callback.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400118 *
n8willis41b46a32020-04-26 16:01:31 +0100119 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400120 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430121 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400122 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400123hb_face_t *
124hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
125 void *user_data,
126 hb_destroy_func_t destroy)
127{
128 hb_face_t *face;
129
130 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
131 if (destroy)
132 destroy (user_data);
133 return hb_face_get_empty ();
134 }
135
136 face->reference_table_func = reference_table_func;
137 face->user_data = user_data;
138 face->destroy = destroy;
139
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600140 face->num_glyphs = -1;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400141
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500142 face->data.init0 (face);
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500143 face->table.init0 (face);
144
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400145 return face;
146}
147
148
149typedef struct hb_face_for_data_closure_t {
150 hb_blob_t *blob;
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700151 uint16_t index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400152} hb_face_for_data_closure_t;
153
154static hb_face_for_data_closure_t *
155_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
156{
157 hb_face_for_data_closure_t *closure;
158
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600159 closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400160 if (unlikely (!closure))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200161 return nullptr;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400162
163 closure->blob = blob;
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700164 closure->index = (uint16_t) (index & 0xFFFFu);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400165
166 return closure;
167}
168
169static void
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200170_hb_face_for_data_closure_destroy (void *data)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400171{
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200172 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
173
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400174 hb_blob_destroy (closure->blob);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600175 hb_free (closure);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400176}
177
178static hb_blob_t *
179_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
180{
181 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
182
183 if (tag == HB_TAG_NONE)
184 return hb_blob_reference (data->blob);
185
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700186 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200187 unsigned int base_offset;
188 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400189
190 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
191
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200192 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400193
194 return blob;
195}
196
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400197/**
Behdad Esfahbodf78a2502022-06-05 00:55:35 -0600198 * hb_face_create:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100199 * @blob: #hb_blob_t to work upon
200 * @index: The index of the face within @blob
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400201 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100202 * Constructs a new face object from the specified blob and
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700203 * a face index into that blob.
204 *
205 * The face index is used for blobs of file formats such as TTC and
Josef Friedrichac4c3b32023-04-17 20:13:43 +0200206 * DFont that can contain more than one face. Face indices within
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700207 * such collections are zero-based.
208 *
209 * <note>Note: If the blob font format is not a collection, @index
210 * is ignored. Otherwise, only the lower 16-bits of @index are used.
211 * The unmodified @index can be accessed via hb_face_get_index().</note>
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430212 *
Behdad Esfahbod2d42fc92022-01-02 07:45:10 -0700213 * <note>Note: The high 16-bits of @index, if non-zero, are used by
214 * hb_font_create() to load named-instances in variable fonts. See
215 * hb_font_create() for details.</note>
216 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100217 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400218 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430219 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400220 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400221hb_face_t *
222hb_face_create (hb_blob_t *blob,
223 unsigned int index)
224{
225 hb_face_t *face;
226
Behdad Esfahbodeb0bf3a2014-08-06 15:36:41 -0400227 if (unlikely (!blob))
228 blob = hb_blob_get_empty ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400229
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800230 blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
231
232 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (blob, index);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400233
234 if (unlikely (!closure))
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800235 {
236 hb_blob_destroy (blob);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400237 return hb_face_get_empty ();
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800238 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400239
240 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
241 closure,
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200242 _hb_face_for_data_closure_destroy);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400243
Behdad Esfahbodd3d36912017-02-03 15:42:03 -0800244 face->index = index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400245
246 return face;
247}
248
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400249/**
250 * hb_face_get_empty:
251 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100252 * Fetches the singleton empty face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430253 *
Khaled Hosny3d7a3612020-12-30 23:58:37 +0200254 * Return value: (transfer full): The empty face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400255 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430256 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400257 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400258hb_face_t *
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330259hb_face_get_empty ()
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400260{
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430261 return const_cast<hb_face_t *> (&Null (hb_face_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400262}
263
264
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400265/**
266 * hb_face_reference: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100267 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400268 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100269 * Increases the reference count on a face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400270 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100271 * Return value: The @face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400272 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430273 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400274 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400275hb_face_t *
276hb_face_reference (hb_face_t *face)
277{
278 return hb_object_reference (face);
279}
280
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400281/**
282 * hb_face_destroy: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100283 * @face: A face object
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200284 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100285 * Decreases the reference count on a face object. When the
286 * reference count reaches zero, the face is destroyed,
287 * freeing all memory.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400288 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430289 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400290 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400291void
292hb_face_destroy (hb_face_t *face)
293{
294 if (!hb_object_destroy (face)) return;
295
Behdad Esfahbod1a5c7492022-12-04 15:20:51 -0700296#ifndef HB_NO_SHAPER
Behdad Esfahbodf6fc5572018-11-05 13:23:54 -0500297 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400298 {
299 hb_face_t::plan_node_t *next = node->next;
300 hb_shape_plan_destroy (node->shape_plan);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600301 hb_free (node);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400302 node = next;
303 }
Behdad Esfahbod1a5c7492022-12-04 15:20:51 -0700304#endif
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400305
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500306 face->data.fini ();
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500307 face->table.fini ();
308
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400309 if (face->destroy)
310 face->destroy (face->user_data);
311
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600312 hb_free (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400313}
314
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400315/**
316 * hb_face_set_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100317 * @face: A face object
318 * @key: The user-data key to set
319 * @data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200320 * @destroy: (nullable): A callback to call when @data is not needed anymore
Nathan Willis3e72feb2019-04-22 19:21:27 +0100321 * @replace: Whether to replace an existing data with the same key
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400322 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200323 * Attaches a user-data key/data pair to the given face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400324 *
Khaled Hosny98e90cc2022-06-30 08:43:57 +0200325 * Return value: `true` if success, `false` otherwise
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400326 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430327 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400328 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400329hb_bool_t
330hb_face_set_user_data (hb_face_t *face,
331 hb_user_data_key_t *key,
332 void * data,
333 hb_destroy_func_t destroy,
334 hb_bool_t replace)
335{
336 return hb_object_set_user_data (face, key, data, destroy, replace);
337}
338
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400339/**
340 * hb_face_get_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100341 * @face: A face object
342 * @key: The user-data key to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400343 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100344 * Fetches the user data associated with the specified key,
345 * attached to the specified face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430346 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100347 * Return value: (transfer none): A pointer to the user data
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400348 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430349 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400350 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400351void *
Behdad Esfahbod1945b402022-07-25 10:45:55 -0600352hb_face_get_user_data (const hb_face_t *face,
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400353 hb_user_data_key_t *key)
354{
355 return hb_object_get_user_data (face, key);
356}
357
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400358/**
359 * hb_face_make_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 * Makes the given face object immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400363 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430364 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400365 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400366void
367hb_face_make_immutable (hb_face_t *face)
368{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400369 if (hb_object_is_immutable (face))
Behdad Esfahbod90a0f9f2018-09-26 15:03:07 -0400370 return;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400371
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400372 hb_object_make_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400373}
374
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400375/**
376 * hb_face_is_immutable:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100377 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400378 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100379 * Tests whether the given face object is immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400380 *
Khaled Hosny98e90cc2022-06-30 08:43:57 +0200381 * Return value: `true` is @face is immutable, `false` otherwise
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400382 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430383 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400384 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400385hb_bool_t
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700386hb_face_is_immutable (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400387{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400388 return hb_object_is_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400389}
390
391
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400392/**
393 * hb_face_reference_table:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100394 * @face: A face object
395 * @tag: The #hb_tag_t of the table to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400396 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100397 * Fetches a reference to the specified table within
398 * the specified face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430399 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100400 * Return value: (transfer full): A pointer to the @tag table within @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400401 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430402 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400403 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400404hb_blob_t *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700405hb_face_reference_table (const hb_face_t *face,
406 hb_tag_t tag)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400407{
Ebrahim Byagowif441a7c2019-09-01 02:18:09 +0430408 if (unlikely (tag == HB_TAG_NONE))
409 return hb_blob_get_empty ();
410
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400411 return face->reference_table (tag);
412}
413
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400414/**
415 * hb_face_reference_blob:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100416 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400417 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100418 * Fetches a pointer to the binary blob that contains the
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200419 * specified face. Returns an empty blob if referencing face data is not
420 * possible.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430421 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100422 * Return value: (transfer full): A pointer to the blob for @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400423 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200424 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400425 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400426hb_blob_t *
427hb_face_reference_blob (hb_face_t *face)
428{
429 return face->reference_table (HB_TAG_NONE);
430}
431
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400432/**
433 * hb_face_set_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100434 * @face: A face object
435 * @index: The index to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400436 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100437 * Assigns the specified face-index to @face. Fails if the
438 * face is immutable.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430439 *
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700440 * <note>Note: changing the index has no effect on the face itself
441 * This only changes the value returned by hb_face_get_index().</note>
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400442 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200443 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400444 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400445void
446hb_face_set_index (hb_face_t *face,
447 unsigned int index)
448{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400449 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400450 return;
451
452 face->index = index;
453}
454
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400455/**
456 * hb_face_get_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100457 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400458 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100459 * Fetches the face-index corresponding to the given face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400460 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100461 * <note>Note: face indices within a collection are zero-based.</note>
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430462 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200463 * Return value: The index of @face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400464 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200465 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400466 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400467unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700468hb_face_get_index (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400469{
470 return face->index;
471}
472
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400473/**
474 * hb_face_set_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100475 * @face: A face object
476 * @upem: The units-per-em value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400477 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100478 * Sets the units-per-em (upem) for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400479 *
Behdad Esfahbodcb509d92023-01-10 13:11:48 -0700480 * This API is used in rare circumstances.
481 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200482 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400483 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400484void
485hb_face_set_upem (hb_face_t *face,
486 unsigned int upem)
487{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400488 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400489 return;
490
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600491 face->upem = upem;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400492}
493
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400494/**
495 * hb_face_get_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100496 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400497 *
Behdad Esfahbod8a2efbd2023-01-10 13:10:36 -0700498 * Fetches the units-per-em (UPEM) value of the specified face object.
499 *
500 * Typical UPEM values for fonts are 1000, or 2048, but any value
501 * in between 16 and 16,384 is allowed for OpenType fonts.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400502 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100503 * Return value: The upem value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400504 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430505 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400506 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400507unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700508hb_face_get_upem (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400509{
510 return face->get_upem ();
511}
512
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400513/**
514 * hb_face_set_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100515 * @face: A face object
516 * @glyph_count: The glyph-count value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400517 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100518 * Sets the glyph count for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400519 *
Behdad Esfahbodcb509d92023-01-10 13:11:48 -0700520 * This API is used in rare circumstances.
521 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200522 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400523 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400524void
525hb_face_set_glyph_count (hb_face_t *face,
526 unsigned int glyph_count)
527{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400528 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400529 return;
530
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600531 face->num_glyphs = glyph_count;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400532}
533
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400534/**
535 * hb_face_get_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100536 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400537 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100538 * Fetches the glyph-count value of the specified face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400539 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100540 * Return value: The glyph-count value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400541 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200542 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400543 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400544unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700545hb_face_get_glyph_count (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400546{
547 return face->get_num_glyphs ();
548}
549
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200550/**
551 * hb_face_get_table_tags:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100552 * @face: A face object
553 * @start_offset: The index of first table tag to retrieve
554 * @table_count: (inout): Input = the maximum number of table tags to return;
555 * Output = the actual number of table tags returned (may be zero)
556 * @table_tags: (out) (array length=table_count): The array of table tags found
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200557 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100558 * Fetches a list of all table tags for a face, if possible. The list returned will
559 * begin at the offset provided
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200560 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100561 * Return value: Total number of tables, or zero if it is not possible to list
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200562 *
563 * Since: 1.6.0
564 **/
565unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700566hb_face_get_table_tags (const hb_face_t *face,
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200567 unsigned int start_offset,
568 unsigned int *table_count, /* IN/OUT */
569 hb_tag_t *table_tags /* OUT */)
570{
prrace498e4372018-06-09 16:04:28 -0700571 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200572 {
573 if (table_count)
574 *table_count = 0;
575 return 0;
576 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400577
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200578 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
579
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700580 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200581 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
582
583 return ot_face.get_table_tags (start_offset, table_count, table_tags);
584}
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700585
586
587/*
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700588 * Character set.
589 */
590
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700591
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700592#ifndef HB_NO_FACE_COLLECT_UNICODES
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700593/**
594 * hb_face_collect_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100595 * @face: A face object
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700596 * @out: (out): The set to add Unicode characters to
Nathan Willis3e72feb2019-04-22 19:21:27 +0100597 *
598 * Collects all of the Unicode characters covered by @face and adds
599 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700600 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200601 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700602 */
603void
604hb_face_collect_unicodes (hb_face_t *face,
605 hb_set_t *out)
606{
Michiharu Ariza5ab50ee2020-02-29 01:32:29 -0800607 face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700608}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700609/**
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700610 * hb_face_collect_nominal_glyph_mapping:
611 * @face: A face object
612 * @mapping: (out): The map to add Unicode-to-glyph mapping to
Khaled Hosnyfcb51112023-01-21 00:24:50 +0200613 * @unicodes: (nullable) (out): The set to add Unicode characters to, or `NULL`
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700614 *
615 * Collects the mapping from Unicode characters to nominal glyphs of the @face,
Matthias Clasen381ac2f2023-01-05 17:48:09 -0500616 * and optionally all of the Unicode characters covered by @face.
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700617 *
Khaled Hosny8bdaedd2023-02-11 23:44:58 +0200618 * Since: 7.0.0
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700619 */
620void
621hb_face_collect_nominal_glyph_mapping (hb_face_t *face,
622 hb_map_t *mapping,
623 hb_set_t *unicodes)
624{
Behdad Esfahbode8ac0ef2023-01-05 16:20:43 -0700625 hb_set_t stack_unicodes;
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700626 if (!unicodes)
Behdad Esfahbode8ac0ef2023-01-05 16:20:43 -0700627 unicodes = &stack_unicodes;
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700628 face->table.cmap->collect_mapping (unicodes, mapping, face->get_num_glyphs ());
629}
630/**
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700631 * hb_face_collect_variation_selectors:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100632 * @face: A face object
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700633 * @out: (out): The set to add Variation Selector characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700634 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100635 * Collects all Unicode "Variation Selector" characters covered by @face and adds
636 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700637 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200638 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700639 */
640void
641hb_face_collect_variation_selectors (hb_face_t *face,
642 hb_set_t *out)
643{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500644 face->table.cmap->collect_variation_selectors (out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700645}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700646/**
647 * hb_face_collect_variation_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100648 * @face: A face object
649 * @variation_selector: The Variation Selector to query
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700650 * @out: (out): The set to add Unicode characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700651 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100652 * Collects all Unicode characters for @variation_selector covered by @face and adds
653 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700654 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200655 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700656 */
657void
658hb_face_collect_variation_unicodes (hb_face_t *face,
659 hb_codepoint_t variation_selector,
660 hb_set_t *out)
661{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500662 face->table.cmap->collect_variation_unicodes (variation_selector, out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700663}
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700664#endif