blob: 79ca02fce9c7fa7546e91c0c5bab5feb526ca313 [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.
50 **/
51
52
53/**
Behdad Esfahbod55bae682018-09-24 10:43:06 -040054 * hb_face_count:
55 * @blob: a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043056 *
Nathan Willis3e72feb2019-04-22 19:21:27 +010057 * Fetches the number of faces in a blob.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043058 *
Behdad Esfahbod55bae682018-09-24 10:43:06 -040059 * Return value: Number of faces in @blob
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043060 *
Behdad Esfahboddf01f3e2018-06-05 15:17:39 -070061 * Since: 1.7.7
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043062 **/
63unsigned int
64hb_face_count (hb_blob_t *blob)
65{
66 if (unlikely (!blob))
67 return 0;
68
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020069 /* TODO We shouldn't be sanitizing blob. Port to run sanitizer and return if not sane. */
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -070070 /* Make API signature const after. */
Behdad Esfahboded7b2e52018-08-01 23:59:09 -070071 hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
Ebrahim Byagowi8220ef82018-06-05 22:50:53 +043072 const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020073 unsigned int ret = ot.get_face_count ();
74 hb_blob_destroy (sanitized);
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043075
Behdad Esfahbod1e9e3442018-07-17 19:17:59 +020076 return ret;
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +043077}
78
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040079/*
80 * hb_face_t
81 */
82
Behdad Esfahbod35066722018-08-06 06:17:48 -070083DEFINE_NULL_INSTANCE (hb_face_t) =
84{
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040085 HB_OBJECT_HEADER_STATIC,
86
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020087 nullptr, /* reference_table_func */
88 nullptr, /* user_data */
89 nullptr, /* destroy */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040090
91 0, /* index */
Behdad Esfahbod140797d2020-06-29 03:51:09 -070092 1000, /* upem */
93 0, /* num_glyphs */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040094
Behdad Esfahbode88d47b2018-11-11 16:25:43 -050095 /* Zero for the rest is fine. */
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -040096};
97
98
Behdad Esfahbod288f2892013-09-06 15:40:22 -040099/**
100 * hb_face_create_for_tables:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100101 * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function
102 * @user_data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200103 * @destroy: (nullable): A callback to call when @data is not needed anymore
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400104 *
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200105 * Variant of hb_face_create(), built for those cases where it is more
106 * convenient to provide data for individual tables instead of the whole font
107 * data. With the caveat that hb_face_get_table_tags() does not currently work
108 * with faces created this way.
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200109 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100110 * Creates a new face object from the specified @user_data and @reference_table_func,
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200111 * with the @destroy callback.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400112 *
n8willis41b46a32020-04-26 16:01:31 +0100113 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400114 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430115 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400116 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400117hb_face_t *
118hb_face_create_for_tables (hb_reference_table_func_t reference_table_func,
119 void *user_data,
120 hb_destroy_func_t destroy)
121{
122 hb_face_t *face;
123
124 if (!reference_table_func || !(face = hb_object_create<hb_face_t> ())) {
125 if (destroy)
126 destroy (user_data);
127 return hb_face_get_empty ();
128 }
129
130 face->reference_table_func = reference_table_func;
131 face->user_data = user_data;
132 face->destroy = destroy;
133
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600134 face->num_glyphs = -1;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400135
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500136 face->data.init0 (face);
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500137 face->table.init0 (face);
138
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400139 return face;
140}
141
142
143typedef struct hb_face_for_data_closure_t {
144 hb_blob_t *blob;
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700145 uint16_t index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400146} hb_face_for_data_closure_t;
147
148static hb_face_for_data_closure_t *
149_hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
150{
151 hb_face_for_data_closure_t *closure;
152
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600153 closure = (hb_face_for_data_closure_t *) hb_calloc (1, sizeof (hb_face_for_data_closure_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400154 if (unlikely (!closure))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200155 return nullptr;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400156
157 closure->blob = blob;
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700158 closure->index = (uint16_t) (index & 0xFFFFu);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400159
160 return closure;
161}
162
163static void
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200164_hb_face_for_data_closure_destroy (void *data)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400165{
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200166 hb_face_for_data_closure_t *closure = (hb_face_for_data_closure_t *) data;
167
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400168 hb_blob_destroy (closure->blob);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600169 hb_free (closure);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400170}
171
172static hb_blob_t *
173_hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
174{
175 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
176
177 if (tag == HB_TAG_NONE)
178 return hb_blob_reference (data->blob);
179
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700180 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200181 unsigned int base_offset;
182 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400183
184 const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
185
Behdad Esfahbod9479ffe2018-09-11 16:41:26 +0200186 hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400187
188 return blob;
189}
190
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400191/**
Behdad Esfahbodf78a2502022-06-05 00:55:35 -0600192 * hb_face_create:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100193 * @blob: #hb_blob_t to work upon
194 * @index: The index of the face within @blob
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400195 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100196 * Constructs a new face object from the specified blob and
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700197 * a face index into that blob.
198 *
199 * The face index is used for blobs of file formats such as TTC and
200 * and DFont that can contain more than one face. Face indices within
201 * such collections are zero-based.
202 *
203 * <note>Note: If the blob font format is not a collection, @index
204 * is ignored. Otherwise, only the lower 16-bits of @index are used.
205 * The unmodified @index can be accessed via hb_face_get_index().</note>
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430206 *
Behdad Esfahbod2d42fc92022-01-02 07:45:10 -0700207 * <note>Note: The high 16-bits of @index, if non-zero, are used by
208 * hb_font_create() to load named-instances in variable fonts. See
209 * hb_font_create() for details.</note>
210 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100211 * Return value: (transfer full): The new face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400212 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430213 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400214 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400215hb_face_t *
216hb_face_create (hb_blob_t *blob,
217 unsigned int index)
218{
219 hb_face_t *face;
220
Behdad Esfahbodeb0bf3a2014-08-06 15:36:41 -0400221 if (unlikely (!blob))
222 blob = hb_blob_get_empty ();
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400223
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800224 blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
225
226 hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (blob, index);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400227
228 if (unlikely (!closure))
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800229 {
230 hb_blob_destroy (blob);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400231 return hb_face_get_empty ();
Sebastian Rasmussen12a9d572020-06-24 03:25:43 +0800232 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400233
234 face = hb_face_create_for_tables (_hb_face_for_data_reference_table,
235 closure,
Behdad Esfahbode1b6d922017-10-11 15:51:31 +0200236 _hb_face_for_data_closure_destroy);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400237
Behdad Esfahbodd3d36912017-02-03 15:42:03 -0800238 face->index = index;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400239
240 return face;
241}
242
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400243/**
244 * hb_face_get_empty:
245 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100246 * Fetches the singleton empty face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430247 *
Khaled Hosny3d7a3612020-12-30 23:58:37 +0200248 * Return value: (transfer full): The empty face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400249 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430250 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400251 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400252hb_face_t *
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330253hb_face_get_empty ()
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400254{
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430255 return const_cast<hb_face_t *> (&Null (hb_face_t));
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400256}
257
258
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400259/**
260 * hb_face_reference: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100261 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400262 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100263 * Increases the reference count on a face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400264 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100265 * Return value: The @face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400266 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430267 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400268 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400269hb_face_t *
270hb_face_reference (hb_face_t *face)
271{
272 return hb_object_reference (face);
273}
274
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400275/**
276 * hb_face_destroy: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100277 * @face: A face object
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200278 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100279 * Decreases the reference count on a face object. When the
280 * reference count reaches zero, the face is destroyed,
281 * freeing all memory.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400282 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430283 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400284 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400285void
286hb_face_destroy (hb_face_t *face)
287{
288 if (!hb_object_destroy (face)) return;
289
Behdad Esfahbod1a5c7492022-12-04 15:20:51 -0700290#ifndef HB_NO_SHAPER
Behdad Esfahbodf6fc5572018-11-05 13:23:54 -0500291 for (hb_face_t::plan_node_t *node = face->shape_plans; node; )
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400292 {
293 hb_face_t::plan_node_t *next = node->next;
294 hb_shape_plan_destroy (node->shape_plan);
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600295 hb_free (node);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400296 node = next;
297 }
Behdad Esfahbod1a5c7492022-12-04 15:20:51 -0700298#endif
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400299
Behdad Esfahbodce5da0f2018-11-16 02:29:13 -0500300 face->data.fini ();
Behdad Esfahbod914b5952018-11-05 22:39:50 -0500301 face->table.fini ();
302
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400303 if (face->destroy)
304 face->destroy (face->user_data);
305
Behdad Esfahbod2337f0d2021-07-08 10:58:50 -0600306 hb_free (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400307}
308
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400309/**
310 * hb_face_set_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100311 * @face: A face object
312 * @key: The user-data key to set
313 * @data: A pointer to the user data
Khaled Hosny99364902020-12-31 00:19:29 +0200314 * @destroy: (nullable): A callback to call when @data is not needed anymore
Nathan Willis3e72feb2019-04-22 19:21:27 +0100315 * @replace: Whether to replace an existing data with the same key
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400316 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200317 * Attaches a user-data key/data pair to the given face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400318 *
Khaled Hosny98e90cc2022-06-30 08:43:57 +0200319 * Return value: `true` if success, `false` otherwise
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 -0400323hb_bool_t
324hb_face_set_user_data (hb_face_t *face,
325 hb_user_data_key_t *key,
326 void * data,
327 hb_destroy_func_t destroy,
328 hb_bool_t replace)
329{
330 return hb_object_set_user_data (face, key, data, destroy, replace);
331}
332
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400333/**
334 * hb_face_get_user_data: (skip)
Nathan Willis3e72feb2019-04-22 19:21:27 +0100335 * @face: A face object
336 * @key: The user-data key to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400337 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100338 * Fetches the user data associated with the specified key,
339 * attached to the specified face object.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430340 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100341 * Return value: (transfer none): A pointer to the user data
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400342 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430343 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400344 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400345void *
Behdad Esfahbod1945b402022-07-25 10:45:55 -0600346hb_face_get_user_data (const hb_face_t *face,
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400347 hb_user_data_key_t *key)
348{
349 return hb_object_get_user_data (face, key);
350}
351
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400352/**
353 * hb_face_make_immutable:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100354 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400355 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100356 * Makes the given face object immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400357 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430358 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400359 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400360void
361hb_face_make_immutable (hb_face_t *face)
362{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400363 if (hb_object_is_immutable (face))
Behdad Esfahbod90a0f9f2018-09-26 15:03:07 -0400364 return;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400365
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400366 hb_object_make_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400367}
368
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400369/**
370 * hb_face_is_immutable:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100371 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400372 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100373 * Tests whether the given face object is immutable.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400374 *
Khaled Hosny98e90cc2022-06-30 08:43:57 +0200375 * Return value: `true` is @face is immutable, `false` otherwise
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400376 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430377 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400378 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400379hb_bool_t
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700380hb_face_is_immutable (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400381{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400382 return hb_object_is_immutable (face);
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400383}
384
385
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400386/**
387 * hb_face_reference_table:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100388 * @face: A face object
389 * @tag: The #hb_tag_t of the table to query
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400390 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100391 * Fetches a reference to the specified table within
392 * the specified face.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430393 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100394 * Return value: (transfer full): A pointer to the @tag table within @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400395 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430396 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400397 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400398hb_blob_t *
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700399hb_face_reference_table (const hb_face_t *face,
400 hb_tag_t tag)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400401{
Ebrahim Byagowif441a7c2019-09-01 02:18:09 +0430402 if (unlikely (tag == HB_TAG_NONE))
403 return hb_blob_get_empty ();
404
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400405 return face->reference_table (tag);
406}
407
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400408/**
409 * hb_face_reference_blob:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100410 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400411 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100412 * Fetches a pointer to the binary blob that contains the
Khaled Hosnycc7b3a12020-09-26 10:22:39 +0200413 * specified face. Returns an empty blob if referencing face data is not
414 * possible.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430415 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100416 * Return value: (transfer full): A pointer to the blob for @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400417 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200418 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400419 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400420hb_blob_t *
421hb_face_reference_blob (hb_face_t *face)
422{
423 return face->reference_table (HB_TAG_NONE);
424}
425
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400426/**
427 * hb_face_set_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100428 * @face: A face object
429 * @index: The index to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400430 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100431 * Assigns the specified face-index to @face. Fails if the
432 * face is immutable.
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430433 *
Behdad Esfahbodda7dba02022-01-01 11:20:20 -0700434 * <note>Note: changing the index has no effect on the face itself
435 * This only changes the value returned by hb_face_get_index().</note>
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400436 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200437 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400438 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400439void
440hb_face_set_index (hb_face_t *face,
441 unsigned int index)
442{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400443 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400444 return;
445
446 face->index = index;
447}
448
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400449/**
450 * hb_face_get_index:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100451 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400452 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100453 * Fetches the face-index corresponding to the given face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400454 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100455 * <note>Note: face indices within a collection are zero-based.</note>
Ebrahim Byagowi32da0c62018-06-05 18:56:26 +0430456 *
Khaled Hosny4811e8f2021-06-07 10:54:36 +0200457 * Return value: The index of @face.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400458 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200459 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400460 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400461unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700462hb_face_get_index (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400463{
464 return face->index;
465}
466
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400467/**
468 * hb_face_set_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100469 * @face: A face object
470 * @upem: The units-per-em value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400471 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100472 * Sets the units-per-em (upem) for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400473 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200474 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400475 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400476void
477hb_face_set_upem (hb_face_t *face,
478 unsigned int upem)
479{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400480 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400481 return;
482
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600483 face->upem = upem;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400484}
485
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400486/**
487 * hb_face_get_upem:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100488 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400489 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100490 * Fetches the units-per-em (upem) value of the specified face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400491 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100492 * Return value: The upem value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400493 *
Behdad Esfahbod5d74ff02015-09-03 14:55:59 +0430494 * Since: 0.9.2
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400495 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400496unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700497hb_face_get_upem (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400498{
499 return face->get_upem ();
500}
501
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400502/**
503 * hb_face_set_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100504 * @face: A face object
505 * @glyph_count: The glyph-count value to assign
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400506 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100507 * Sets the glyph count for a face object to the specified value.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400508 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200509 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400510 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400511void
512hb_face_set_glyph_count (hb_face_t *face,
513 unsigned int glyph_count)
514{
Behdad Esfahbod5570c872018-11-03 14:51:38 -0400515 if (hb_object_is_immutable (face))
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400516 return;
517
Behdad Esfahbodf73c15c2022-08-03 12:54:03 -0600518 face->num_glyphs = glyph_count;
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400519}
520
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400521/**
522 * hb_face_get_glyph_count:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100523 * @face: A face object
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400524 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100525 * Fetches the glyph-count value of the specified face object.
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400526 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100527 * Return value: The glyph-count value of @face
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400528 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200529 * Since: 0.9.7
Behdad Esfahbod288f2892013-09-06 15:40:22 -0400530 **/
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400531unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700532hb_face_get_glyph_count (const hb_face_t *face)
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400533{
534 return face->get_num_glyphs ();
535}
536
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200537/**
538 * hb_face_get_table_tags:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100539 * @face: A face object
540 * @start_offset: The index of first table tag to retrieve
541 * @table_count: (inout): Input = the maximum number of table tags to return;
542 * Output = the actual number of table tags returned (may be zero)
543 * @table_tags: (out) (array length=table_count): The array of table tags found
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200544 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100545 * Fetches a list of all table tags for a face, if possible. The list returned will
546 * begin at the offset provided
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200547 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100548 * Return value: Total number of tables, or zero if it is not possible to list
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200549 *
550 * Since: 1.6.0
551 **/
552unsigned int
Behdad Esfahbod16ccfaf2018-08-01 22:50:06 -0700553hb_face_get_table_tags (const hb_face_t *face,
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200554 unsigned int start_offset,
555 unsigned int *table_count, /* IN/OUT */
556 hb_tag_t *table_tags /* OUT */)
557{
prrace498e4372018-06-09 16:04:28 -0700558 if (face->destroy != (hb_destroy_func_t) _hb_face_for_data_closure_destroy)
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200559 {
560 if (table_count)
561 *table_count = 0;
562 return 0;
563 }
Behdad Esfahbod2e3a07a2013-08-26 18:49:07 -0400564
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200565 hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) face->user_data;
566
Behdad Esfahbodeba1c162018-05-08 02:47:42 -0700567 const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
Behdad Esfahbod94b3caf2017-10-11 17:22:44 +0200568 const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
569
570 return ot_face.get_table_tags (start_offset, table_count, table_tags);
571}
Behdad Esfahbodaadb2a92018-08-25 08:18:53 -0700572
573
574/*
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700575 * Character set.
576 */
577
Behdad Esfahboda84309a2018-08-26 09:33:01 -0700578
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700579#ifndef HB_NO_FACE_COLLECT_UNICODES
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700580/**
581 * hb_face_collect_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100582 * @face: A face object
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700583 * @out: (out): The set to add Unicode characters to
Nathan Willis3e72feb2019-04-22 19:21:27 +0100584 *
585 * Collects all of the Unicode characters covered by @face and adds
586 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700587 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200588 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700589 */
590void
591hb_face_collect_unicodes (hb_face_t *face,
592 hb_set_t *out)
593{
Michiharu Ariza5ab50ee2020-02-29 01:32:29 -0800594 face->table.cmap->collect_unicodes (out, face->get_num_glyphs ());
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700595}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700596/**
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700597 * hb_face_collect_nominal_glyph_mapping:
598 * @face: A face object
599 * @mapping: (out): The map to add Unicode-to-glyph mapping to
600 * @unicodes: (nullable) (out): The set to add Unicode characters to, or %NULL
601 *
602 * Collects the mapping from Unicode characters to nominal glyphs of the @face,
603 * and optionall all of the Unicode characters covered by @face.
604 *
605 * Since: REPLACEME
606 */
607void
608hb_face_collect_nominal_glyph_mapping (hb_face_t *face,
609 hb_map_t *mapping,
610 hb_set_t *unicodes)
611{
612 hb_set_t static_unicodes;
613 if (!unicodes)
614 unicodes = &static_unicodes;
615 face->table.cmap->collect_mapping (unicodes, mapping, face->get_num_glyphs ());
616}
617/**
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700618 * hb_face_collect_variation_selectors:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100619 * @face: A face object
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700620 * @out: (out): The set to add Variation Selector characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700621 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100622 * Collects all Unicode "Variation Selector" characters covered by @face and adds
623 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700624 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200625 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700626 */
627void
628hb_face_collect_variation_selectors (hb_face_t *face,
629 hb_set_t *out)
630{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500631 face->table.cmap->collect_variation_selectors (out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700632}
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700633/**
634 * hb_face_collect_variation_unicodes:
Nathan Willis3e72feb2019-04-22 19:21:27 +0100635 * @face: A face object
636 * @variation_selector: The Variation Selector to query
Behdad Esfahbodc54debc2023-01-05 11:54:06 -0700637 * @out: (out): The set to add Unicode characters to
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700638 *
Nathan Willis3e72feb2019-04-22 19:21:27 +0100639 * Collects all Unicode characters for @variation_selector covered by @face and adds
640 * them to the #hb_set_t set @out.
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700641 *
Behdad Esfahbod54d332d2018-09-10 11:37:24 +0200642 * Since: 1.9.0
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700643 */
644void
645hb_face_collect_variation_unicodes (hb_face_t *face,
646 hb_codepoint_t variation_selector,
647 hb_set_t *out)
648{
Behdad Esfahbod0fe7a742018-11-05 23:08:33 -0500649 face->table.cmap->collect_variation_unicodes (variation_selector, out);
Behdad Esfahboddae39c52018-08-25 22:44:39 -0700650}
Behdad Esfahbod27de7c42019-06-19 20:07:02 -0700651#endif