blob: 8c90e689846d712a24265993c22f45392ad60ac9 [file] [log] [blame]
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +01001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 2009,2010 Red Hat, Inc.
Behdad Esfahbod07d68282012-08-10 03:28:50 -04003 * Copyright © 2010,2011,2012 Google, Inc.
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +01004 *
Behdad Esfahbodc755cb32010-04-22 00:11:43 -04005 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +01006 *
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
Behdad Esfahbod476c9422010-10-07 17:47:33 -040026 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +010027 */
28
Behdad Esfahbod027857d2012-07-26 17:34:25 -040029#define HB_SHAPER ot
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -070030#define hb_ot_shape_plan_data_t hb_ot_shape_plan_t
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070031#include "hb-shaper-impl.hh"
Behdad Esfahbod027857d2012-07-26 17:34:25 -040032
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070033#include "hb-ot-shape.hh"
34#include "hb-ot-shape-complex.hh"
35#include "hb-ot-shape-fallback.hh"
36#include "hb-ot-shape-normalize.hh"
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +010037
Behdad Esfahbodb9291002018-08-26 01:15:47 -070038#include "hb-ot-face.hh"
Behdad Esfahbod10b6c7c2018-10-02 13:11:18 +020039
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070040#include "hb-set.hh"
Behdad Esfahbod72657e42011-05-02 20:46:32 -040041
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070042#include "hb-aat-layout.hh"
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040043
Behdad Esfahbod1d1734e2018-10-02 13:04:05 +020044
45void
46hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
47 const int *coords,
48 unsigned int num_coords)
49{
50 plan.props = props;
51 plan.shaper = shaper;
52 map.compile (plan.map, coords, num_coords);
53
54 plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
55 plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
56 plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
57 plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
58
59 plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
60 HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
61
62 plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
63 plan.kerning_requested = !!plan.kern_mask;
64 plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
Behdad Esfahbod96eca872018-10-02 13:24:40 +020065
Behdad Esfahbod48c513f2018-10-02 14:17:42 +020066 bool disable_gpos = plan.shaper->gpos_tag &&
67 plan.shaper->gpos_tag != plan.map.chosen_script[1];
68 plan.fallback_positioning = disable_gpos || !hb_ot_layout_has_positioning (face);
69 plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face);
Behdad Esfahbod1d1734e2018-10-02 13:04:05 +020070}
71
72
Behdad Esfahbod94d15522018-10-02 14:45:09 +020073static const hb_ot_map_feature_t
74common_features[] =
Behdad Esfahbod1d1734e2018-10-02 13:04:05 +020075{
Behdad Esfahbod94d15522018-10-02 14:45:09 +020076 {HB_TAG('c','c','m','p'), F_GLOBAL},
77 {HB_TAG('l','o','c','l'), F_GLOBAL},
78 {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
79 {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
80 {HB_TAG('r','l','i','g'), F_GLOBAL},
Behdad Esfahbod89a2bc92011-05-31 15:18:13 -040081};
82
Behdad Esfahbodd1deaa22012-05-09 15:04:13 +020083
Behdad Esfahbod94d15522018-10-02 14:45:09 +020084static const hb_ot_map_feature_t
85horizontal_features[] =
Behdad Esfahbod1d1734e2018-10-02 13:04:05 +020086{
Behdad Esfahbod94d15522018-10-02 14:45:09 +020087 {HB_TAG('c','a','l','t'), F_GLOBAL},
88 {HB_TAG('c','l','i','g'), F_GLOBAL},
89 {HB_TAG('c','u','r','s'), F_GLOBAL},
90 {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
91 {HB_TAG('l','i','g','a'), F_GLOBAL},
92 {HB_TAG('r','c','l','t'), F_GLOBAL},
Behdad Esfahbod89a2bc92011-05-31 15:18:13 -040093};
94
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +010095static void
Behdad Esfahbod90645fb2011-05-27 18:13:31 -040096hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
Behdad Esfahbod49baa1f2010-10-12 16:50:36 -040097 const hb_segment_properties_t *props,
Behdad Esfahbod90645fb2011-05-27 18:13:31 -040098 const hb_feature_t *user_features,
99 unsigned int num_user_features)
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +0100100{
Behdad Esfahbod8bb5deb2012-08-02 10:07:58 -0400101 hb_ot_map_builder_t *map = &planner->map;
102
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400103 map->enable_feature (HB_TAG('r','v','r','n'));
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200104 map->add_gsub_pause (nullptr);
Behdad Esfahbod0aedfd52016-09-28 17:05:43 +0200105
Behdad Esfahbod895fb5d2010-10-12 16:00:21 -0400106 switch (props->direction) {
Behdad Esfahbod074ea782010-05-21 17:53:10 +0100107 case HB_DIRECTION_LTR:
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400108 map->enable_feature (HB_TAG ('l','t','r','a'));
109 map->enable_feature (HB_TAG ('l','t','r','m'));
Behdad Esfahbod074ea782010-05-21 17:53:10 +0100110 break;
111 case HB_DIRECTION_RTL:
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400112 map->enable_feature (HB_TAG ('r','t','l','a'));
113 map->add_feature (HB_TAG ('r','t','l','m'));
Behdad Esfahbod0e235d02010-05-28 20:21:47 -0400114 break;
115 case HB_DIRECTION_TTB:
116 case HB_DIRECTION_BTT:
Behdad Esfahbod3286fc02011-03-16 14:53:32 -0300117 case HB_DIRECTION_INVALID:
Behdad Esfahbod0e235d02010-05-28 20:21:47 -0400118 default:
119 break;
120 }
121
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200122 /* Automatic fractions. */
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400123 map->add_feature (HB_TAG ('f','r','a','c'));
124 map->add_feature (HB_TAG ('n','u','m','r'));
125 map->add_feature (HB_TAG ('d','n','o','m'));
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500126
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200127 /* Random! */
Behdad Esfahbod0a371fe2018-10-02 14:48:39 +0200128 map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200129
Behdad Esfahbod693918e2012-07-30 21:08:51 -0400130 if (planner->shaper->collect_features)
Behdad Esfahbod16c6a272012-08-02 09:38:28 -0400131 planner->shaper->collect_features (planner);
Behdad Esfahbode04685e2010-05-28 20:37:06 -0400132
Behdad Esfahbodee9c3a12013-02-15 06:22:26 -0500133 for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
Behdad Esfahbod94d15522018-10-02 14:45:09 +0200134 map->add_feature (common_features[i]);
Behdad Esfahbod89a2bc92011-05-31 15:18:13 -0400135
136 if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
Behdad Esfahbodee9c3a12013-02-15 06:22:26 -0500137 for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
Behdad Esfahbod94d15522018-10-02 14:45:09 +0200138 map->add_feature (horizontal_features[i]);
Behdad Esfahbod89a2bc92011-05-31 15:18:13 -0400139 else
Behdad Esfahbodf327aac2015-07-23 11:32:59 +0100140 {
Behdad Esfahbod0f98fe82015-07-23 11:52:11 +0100141 /* We really want to find a 'vert' feature if there's any in the font, no
142 * matter which script/langsys it is listed (or not) under.
143 * See various bugs referenced from:
ebraminio7c6937e2017-11-20 14:49:22 -0500144 * https://github.com/harfbuzz/harfbuzz/issues/63 */
Behdad Esfahbod0a371fe2018-10-02 14:48:39 +0200145 map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
Behdad Esfahbodf327aac2015-07-23 11:32:59 +0100146 }
Behdad Esfahbod89a2bc92011-05-31 15:18:13 -0400147
Behdad Esfahbod693918e2012-07-30 21:08:51 -0400148 if (planner->shaper->override_features)
Behdad Esfahbod16c6a272012-08-02 09:38:28 -0400149 planner->shaper->override_features (planner);
Behdad Esfahbodd96838e2012-07-16 20:26:57 -0400150
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200151 for (unsigned int i = 0; i < num_user_features; i++)
152 {
Behdad Esfahbod895fb5d2010-10-12 16:00:21 -0400153 const hb_feature_t *feature = &user_features[i];
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400154 map->add_feature (feature->tag,
Behdad Esfahbodd9867492018-09-24 18:11:59 -0400155 (feature->start == HB_FEATURE_GLOBAL_START &&
156 feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
Behdad Esfahbodf048ead2018-09-24 18:01:53 -0400157 feature->value);
Behdad Esfahbode04685e2010-05-28 20:37:06 -0400158 }
Behdad Esfahbode89b7d22010-10-08 12:29:59 -0400159}
Behdad Esfahbod0e235d02010-05-28 20:21:47 -0400160
161
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400162/*
163 * shaper face data
164 */
165
Behdad Esfahbod466b3e52017-02-03 16:43:25 -0800166HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
167
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700168hb_ot_face_data_t *
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400169_hb_ot_shaper_face_data_create (hb_face_t *face)
170{
Behdad Esfahbod1c6b3692018-08-15 20:12:25 -0700171 return _hb_ot_face_data_create (face);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400172}
173
174void
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700175_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400176{
Behdad Esfahbod1c6b3692018-08-15 20:12:25 -0700177 _hb_ot_face_data_destroy (data);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400178}
179
180
181/*
182 * shaper font data
183 */
184
Behdad Esfahbod466b3e52017-02-03 16:43:25 -0800185HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
186
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700187struct hb_ot_font_data_t {};
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400188
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700189hb_ot_font_data_t *
Behdad Esfahbod89137e32016-02-22 16:00:59 +0900190_hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400191{
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700192 return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400193}
194
195void
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700196_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data)
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400197{
198}
199
200
201/*
202 * shaper shape_plan data
203 */
204
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700205hb_ot_shape_plan_data_t *
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400206_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
207 const hb_feature_t *user_features,
Behdad Esfahbod72ada4f2016-09-10 03:57:24 -0700208 unsigned int num_user_features,
209 const int *coords,
210 unsigned int num_coords)
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400211{
Behdad Esfahboda8c6da92012-08-02 10:46:34 -0400212 hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
213 if (unlikely (!plan))
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200214 return nullptr;
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400215
Behdad Esfahbodf9abbf82018-06-02 15:30:59 -0700216 plan->init ();
217
Behdad Esfahbod5393e3a2012-08-02 09:24:35 -0400218 hb_ot_shape_planner_t planner (shape_plan);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400219
Behdad Esfahbod9b37b4c2012-11-12 18:23:38 -0800220 planner.shaper = hb_ot_shape_complex_categorize (&planner);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400221
Behdad Esfahbod72ada4f2016-09-10 03:57:24 -0700222 hb_ot_shape_collect_features (&planner, &shape_plan->props,
223 user_features, num_user_features);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400224
Behdad Esfahbod72ada4f2016-09-10 03:57:24 -0700225 planner.compile (*plan, coords, num_coords);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400226
Behdad Esfahboda8c6da92012-08-02 10:46:34 -0400227 if (plan->shaper->data_create) {
228 plan->data = plan->shaper->data_create (plan);
Behdad Esfahbod42c183f2018-07-27 14:55:29 -0700229 if (unlikely (!plan->data))
230 {
231 free (plan);
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200232 return nullptr;
prrace2e25d8f2018-07-27 13:58:27 -0700233 }
Behdad Esfahboda8c6da92012-08-02 10:46:34 -0400234 }
235
236 return plan;
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400237}
238
239void
Behdad Esfahbod3d22aef2018-08-01 18:03:32 -0700240_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shape_plan_data_t *plan)
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400241{
Behdad Esfahboda8c6da92012-08-02 10:46:34 -0400242 if (plan->shaper->data_destroy)
243 plan->shaper->data_destroy (const_cast<void *> (plan->data));
Behdad Esfahbod4ba647e2012-07-30 09:53:06 -0400244
Behdad Esfahboda60ba792018-05-01 19:01:25 -0400245 plan->fini ();
Behdad Esfahboda8c6da92012-08-02 10:46:34 -0400246
247 free (plan);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400248}
249
250
251/*
252 * shaper
253 */
254
Behdad Esfahbodb9f199c2012-04-14 20:23:58 -0400255struct hb_ot_shape_context_t
256{
Behdad Esfahbodb9f199c2012-04-14 20:23:58 -0400257 hb_ot_shape_plan_t *plan;
258 hb_font_t *font;
259 hb_face_t *face;
260 hb_buffer_t *buffer;
261 const hb_feature_t *user_features;
262 unsigned int num_user_features;
263
264 /* Transient stuff */
265 hb_direction_t target_direction;
Behdad Esfahbodb9f199c2012-04-14 20:23:58 -0400266};
267
Behdad Esfahbod2014b8d2009-12-20 20:58:26 +0100268
269
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100270/* Main shaper */
271
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400272
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100273/* Prepare */
274
Behdad Esfahbodb9f199c2012-04-14 20:23:58 -0400275static void
276hb_set_unicode_props (hb_buffer_t *buffer)
Behdad Esfahbod3a852ae2010-11-03 16:37:24 -0400277{
Behdad Esfahbod3b783182018-10-03 19:44:15 +0200278 /* Implement enough of Unicode Graphemes here that shaping
279 * in reverse-direction wouldn't break graphemes. Namely,
280 * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
281 * sequences as continuations. The foreach_grapheme()
282 * macro uses this bit.
283 *
284 * https://www.unicode.org/reports/tr29/#Regex_Definitions
285 */
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400286 unsigned int count = buffer->len;
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400287 hb_glyph_info_t *info = buffer->info;
Behdad Esfahbod0e336142012-04-12 10:06:52 -0400288 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod3b783182018-10-03 19:44:15 +0200289 {
Behdad Esfahbod69862082015-11-04 18:46:22 -0800290 _hb_glyph_info_set_unicode_props (&info[i], buffer);
Behdad Esfahbod3b783182018-10-03 19:44:15 +0200291
292 /* Marks are already set as continuation by the above line.
293 * Handle ZWJ-continuation. */
294 if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
295 {
296 _hb_glyph_info_set_continuation (&info[i]);
297 if (i + 1 < count &&
298 _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
299 {
300 i++;
301 _hb_glyph_info_set_unicode_props (&info[i], buffer);
302 _hb_glyph_info_set_continuation (&info[i]);
303 }
304 }
305 }
Behdad Esfahbod3a852ae2010-11-03 16:37:24 -0400306}
307
308static void
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400309hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
310{
Behdad Esfahbod0c7df222012-11-13 14:42:35 -0800311 if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
Behdad Esfahbod763e5462014-08-02 16:17:44 -0400312 buffer->context_len[0] ||
Behdad Esfahbod123326e2018-10-03 19:19:51 +0200313 !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400314 return;
315
Behdad Esfahbod76271002014-07-11 14:54:42 -0400316 if (!font->has_glyph (0x25CCu))
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400317 return;
318
Behdad Esfahbod595d2b92014-07-26 18:44:15 -0400319 hb_glyph_info_t dottedcircle = {0};
Behdad Esfahbod76271002014-07-11 14:54:42 -0400320 dottedcircle.codepoint = 0x25CCu;
Behdad Esfahbod69862082015-11-04 18:46:22 -0800321 _hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400322
323 buffer->clear_output ();
324
325 buffer->idx = 0;
326 hb_glyph_info_t info = dottedcircle;
327 info.cluster = buffer->cur().cluster;
328 info.mask = buffer->cur().mask;
329 buffer->output_info (info);
Behdad Esfahbod7185b272018-05-31 20:03:00 -0700330 while (buffer->idx < buffer->len && buffer->successful)
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400331 buffer->next_glyph ();
332
333 buffer->swap_buffers ();
334}
335
336static void
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400337hb_form_clusters (hb_buffer_t *buffer)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100338{
Behdad Esfahbod7cc34802017-09-04 20:04:59 -0700339 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
Behdad Esfahbod376d5872015-07-22 16:51:12 +0100340 return;
341
Behdad Esfahbod7cc34802017-09-04 20:04:59 -0700342 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
Behdad Esfahbod03fb6dd2018-10-03 21:02:16 +0200343 foreach_grapheme (buffer, start, end)
344 buffer->merge_clusters (start, end);
Behdad Esfahbod7cc34802017-09-04 20:04:59 -0700345 else
Behdad Esfahbod03fb6dd2018-10-03 21:02:16 +0200346 foreach_grapheme (buffer, start, end)
347 buffer->unsafe_to_break (start, end);
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100348}
349
Behdad Esfahbod967240d2010-10-05 23:00:05 -0400350static void
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400351hb_ensure_native_direction (hb_buffer_t *buffer)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100352{
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400353 hb_direction_t direction = buffer->props.direction;
Behdad Esfahbodf673cfb2018-05-07 13:58:32 -0700354 hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100355
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400356 /* TODO vertical:
357 * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
358 * Ogham fonts are supposed to be implemented BTT or not. Need to research that
359 * first. */
Behdad Esfahbodf673cfb2018-05-07 13:58:32 -0700360 if ((HB_DIRECTION_IS_HORIZONTAL (direction) &&
361 direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
362 (HB_DIRECTION_IS_VERTICAL (direction) &&
363 direction != HB_DIRECTION_TTB))
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100364 {
Behdad Esfahbodf883de62015-09-01 16:23:40 +0100365
Behdad Esfahbod376d5872015-07-22 16:51:12 +0100366 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
Behdad Esfahbod03fb6dd2018-10-03 21:02:16 +0200367 foreach_grapheme (buffer, start, end)
368 {
369 buffer->merge_clusters (start, end);
370 buffer->reverse_range (start, end);
371 }
372 else
373 foreach_grapheme (buffer, start, end)
374 /* form_clusters() merged clusters already, we don't merge. */
375 buffer->reverse_range (start, end);
Behdad Esfahboda60e2cf2015-07-22 15:49:08 +0100376
377 buffer->reverse ();
378
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400379 buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100380 }
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100381}
382
383
384/* Substitute */
385
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400386static inline void
387hb_ot_mirror_chars (hb_ot_shape_context_t *c)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100388{
Behdad Esfahbodbbbbe802010-12-07 16:22:02 -0500389 if (HB_DIRECTION_IS_FORWARD (c->target_direction))
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100390 return;
391
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200392 hb_buffer_t *buffer = c->buffer;
393 hb_unicode_funcs_t *unicode = buffer->unicode;
Behdad Esfahbod5497a8a2013-12-22 20:48:53 -0500394 hb_mask_t rtlm_mask = c->plan->rtlm_mask;
Behdad Esfahbod4e4ef242010-07-23 17:22:11 -0400395
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200396 unsigned int count = buffer->len;
397 hb_glyph_info_t *info = buffer->info;
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100398 for (unsigned int i = 0; i < count; i++) {
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200399 hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
Behdad Esfahbod7b8b63a2015-07-22 15:24:26 +0100400 if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200401 info[i].mask |= rtlm_mask;
Behdad Esfahbod1094a292010-05-21 17:58:20 +0100402 else
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200403 info[i].codepoint = codepoint;
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100404 }
405}
406
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400407static inline void
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500408hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
409{
Behdad Esfahbode3e4bb02015-11-04 18:58:02 -0800410 if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
411 !c->plan->has_frac)
Behdad Esfahbod5497a8a2013-12-22 20:48:53 -0500412 return;
413
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500414 hb_buffer_t *buffer = c->buffer;
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500415
Khaled Hosny24525432017-01-18 22:48:13 +0200416 hb_mask_t pre_mask, post_mask;
417 if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
418 {
419 pre_mask = c->plan->numr_mask | c->plan->frac_mask;
420 post_mask = c->plan->frac_mask | c->plan->dnom_mask;
421 }
422 else
423 {
424 pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
425 post_mask = c->plan->numr_mask | c->plan->frac_mask;
426 }
427
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500428 unsigned int count = buffer->len;
429 hb_glyph_info_t *info = buffer->info;
430 for (unsigned int i = 0; i < count; i++)
431 {
Behdad Esfahbod76271002014-07-11 14:54:42 -0400432 if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500433 {
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500434 unsigned int start = i, end = i + 1;
435 while (start &&
436 _hb_glyph_info_get_general_category (&info[start - 1]) ==
437 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
438 start--;
439 while (end < count &&
440 _hb_glyph_info_get_general_category (&info[end]) ==
441 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
442 end++;
443
Behdad Esfahbodc449d2d2017-08-30 17:28:22 -0700444 buffer->unsafe_to_break (start, end);
445
Behdad Esfahboda7e8bbb2013-12-22 19:33:35 -0500446 for (unsigned int j = start; j < i; j++)
Khaled Hosny24525432017-01-18 22:48:13 +0200447 info[j].mask |= pre_mask;
Behdad Esfahbod5497a8a2013-12-22 20:48:53 -0500448 info[i].mask |= c->plan->frac_mask;
Behdad Esfahboda7e8bbb2013-12-22 19:33:35 -0500449 for (unsigned int j = i + 1; j < end; j++)
Khaled Hosny24525432017-01-18 22:48:13 +0200450 info[j].mask |= post_mask;
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500451
452 i = end - 1;
453 }
454 }
455}
456
457static inline void
Behdad Esfahbod73932512013-12-21 00:18:18 -0500458hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400459{
460 hb_ot_map_t *map = &c->plan->map;
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200461 hb_buffer_t *buffer = c->buffer;
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400462
463 hb_mask_t global_mask = map->get_global_mask ();
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200464 buffer->reset_masks (global_mask);
Behdad Esfahbod73932512013-12-21 00:18:18 -0500465}
466
467static inline void
468hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
469{
470 hb_ot_map_t *map = &c->plan->map;
471 hb_buffer_t *buffer = c->buffer;
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400472
Behdad Esfahbod3aeee512013-12-22 16:17:54 -0500473 hb_ot_shape_setup_masks_fraction (c);
474
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400475 if (c->plan->shaper->setup_masks)
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200476 c->plan->shaper->setup_masks (c->plan, buffer, c->font);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400477
478 for (unsigned int i = 0; i < c->num_user_features; i++)
479 {
480 const hb_feature_t *feature = &c->user_features[i];
481 if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
482 unsigned int shift;
483 hb_mask_t mask = map->get_mask (feature->tag, &shift);
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200484 buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400485 }
486 }
487}
488
Behdad Esfahbod8cfbc302015-07-22 18:41:10 +0100489static void
490hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
491{
492 hb_buffer_t *buffer = c->buffer;
493
Behdad Esfahbod69862082015-11-04 18:46:22 -0800494 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
Behdad Esfahbod3b1e97f2018-01-10 03:35:20 +0100495 (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
496 (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
Behdad Esfahbod8cfbc302015-07-22 18:41:10 +0100497 return;
498
499 unsigned int count = buffer->len;
500 hb_glyph_info_t *info = buffer->info;
501 hb_glyph_position_t *pos = buffer->pos;
502 unsigned int i = 0;
503 for (i = 0; i < count; i++)
504 if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
505 pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
506}
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100507
508static void
509hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
510{
511 hb_buffer_t *buffer = c->buffer;
512
Behdad Esfahbod69862082015-11-04 18:46:22 -0800513 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
514 (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100515 return;
516
517 unsigned int count = buffer->len;
518 hb_glyph_info_t *info = buffer->info;
519 hb_glyph_position_t *pos = buffer->pos;
520 unsigned int i = 0;
521 for (i = 0; i < count; i++)
522 {
Behdad Esfahbod4ba796b2015-07-22 17:41:31 +0100523 if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100524 break;
525 }
526
527 /* No default-ignorables found; return. */
528 if (i == count)
529 return;
530
531 hb_codepoint_t space;
Behdad Esfahbod3b1e97f2018-01-10 03:35:20 +0100532 if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
533 c->font->get_nominal_glyph (' ', &space))
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100534 {
535 /* Replace default-ignorables with a zero-advance space glyph. */
536 for (/*continue*/; i < count; i++)
537 {
Behdad Esfahbod4ba796b2015-07-22 17:41:31 +0100538 if (_hb_glyph_info_is_default_ignorable (&info[i]))
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100539 info[i].codepoint = space;
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100540 }
541 }
542 else
543 {
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100544 /* Merge clusters and delete default-ignorables.
545 * NOTE! We can't use out-buffer as we have positioning data. */
546 unsigned int j = i;
547 for (; i < count; i++)
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100548 {
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100549 if (_hb_glyph_info_is_default_ignorable (&info[i]))
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100550 {
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100551 /* Merge clusters.
552 * Same logic as buffer->delete_glyph(), but for in-place removal. */
553
554 unsigned int cluster = info[i].cluster;
555 if (i + 1 < count && cluster == info[i + 1].cluster)
556 continue; /* Cluster survives; do nothing. */
557
558 if (j)
559 {
560 /* Merge cluster backward. */
561 if (cluster < info[j - 1].cluster)
562 {
Behdad Esfahbode2a2b5b2017-08-10 20:10:12 -0700563 unsigned int mask = info[i].mask;
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100564 unsigned int old_cluster = info[j - 1].cluster;
565 for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
Behdad Esfahbode2a2b5b2017-08-10 20:10:12 -0700566 buffer->set_cluster (info[k - 1], cluster, mask);
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100567 }
568 continue;
569 }
570
571 if (i + 1 < count)
572 buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
573
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100574 continue;
575 }
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100576
577 if (j != i)
578 {
579 info[j] = info[i];
580 pos[j] = pos[i];
581 }
582 j++;
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100583 }
Behdad Esfahbod2dbd3d22015-07-22 18:28:39 +0100584 buffer->len = j;
Behdad Esfahbodf0010df2015-07-22 17:36:23 +0100585 }
586}
587
588
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400589static inline void
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400590hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100591{
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400592 /* Normalization process sets up glyph_index(), we just copy it. */
593 unsigned int count = buffer->len;
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400594 hb_glyph_info_t *info = buffer->info;
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400595 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400596 info[i].codepoint = info[i].glyph_index();
Behdad Esfahbode47b7722015-08-18 18:42:47 +0100597
598 buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100599}
600
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400601static inline void
Behdad Esfahbod1a0f4aa2016-12-22 13:33:54 -0600602hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
603{
604 unsigned int count = c->buffer->len;
605 hb_glyph_info_t *info = c->buffer->info;
606 for (unsigned int i = 0; i < count; i++)
607 {
608 hb_ot_layout_glyph_props_flags_t klass;
609
610 /* Never mark default-ignorables as marks.
611 * They won't get in the way of lookups anyway,
612 * but having them as mark will cause them to be skipped
613 * over if the lookup-flag says so, but at least for the
614 * Mongolian variation selectors, looks like Uniscribe
615 * marks them as non-mark. Some Mongolian fonts without
616 * GDEF rely on this. Another notable character that
617 * this applies to is COMBINING GRAPHEME JOINER. */
618 klass = (_hb_glyph_info_get_general_category (&info[i]) !=
619 HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
620 _hb_glyph_info_is_default_ignorable (&info[i])) ?
621 HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
622 HB_OT_LAYOUT_GLYPH_PROPS_MARK;
623 _hb_glyph_info_set_glyph_props (&info[i], klass);
624 }
625}
626
627static inline void
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400628hb_ot_substitute_default (hb_ot_shape_context_t *c)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100629{
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200630 hb_buffer_t *buffer = c->buffer;
631
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400632 hb_ot_mirror_chars (c);
Behdad Esfahbodb65c0602011-07-28 16:48:43 -0400633
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200634 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400635
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200636 _hb_ot_shape_normalize (c->plan, buffer, c->font);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400637
638 hb_ot_shape_setup_masks (c);
639
Behdad Esfahbod3992b5e2012-09-01 19:20:41 -0400640 /* This is unfortunate to go here, but necessary... */
Behdad Esfahbod96eca872018-10-02 13:24:40 +0200641 if (c->plan->fallback_positioning)
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200642 _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
Behdad Esfahbod3992b5e2012-09-01 19:20:41 -0400643
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200644 hb_ot_map_glyphs_fast (buffer);
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400645
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200646 HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100647}
648
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400649static inline void
Behdad Esfahbodc86f9322011-07-25 00:44:50 -0400650hb_ot_substitute_complex (hb_ot_shape_context_t *c)
651{
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200652 hb_buffer_t *buffer = c->buffer;
653
654 hb_ot_layout_substitute_start (c->font, buffer);
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400655
Behdad Esfahbodcca757a2018-10-02 13:27:11 +0200656 if (c->plan->fallback_glyph_classes)
Behdad Esfahbod1a0f4aa2016-12-22 13:33:54 -0600657 hb_synthesize_glyph_classes (c);
658
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200659 c->plan->substitute (c->font, buffer);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100660
Behdad Esfahboddb5d4302018-07-17 18:14:45 +0200661 if (0) /* XXX Call morx instead. */
662 hb_aat_layout_substitute (c->font, c->buffer);
Behdad Esfahbodc86f9322011-07-25 00:44:50 -0400663}
664
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400665static inline void
666hb_ot_substitute (hb_ot_shape_context_t *c)
667{
668 hb_ot_substitute_default (c);
Behdad Esfahbod0f407322015-11-04 22:28:44 -0800669
670 _hb_buffer_allocate_gsubgpos_vars (c->buffer);
671
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400672 hb_ot_substitute_complex (c);
673}
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100674
675/* Position */
676
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400677static inline void
Jonathan Kew798e4182014-06-10 13:10:30 +0100678adjust_mark_offsets (hb_glyph_position_t *pos)
679{
680 pos->x_offset -= pos->x_advance;
681 pos->y_offset -= pos->y_advance;
682}
683
684static inline void
685zero_mark_width (hb_glyph_position_t *pos)
686{
687 pos->x_advance = 0;
688 pos->y_advance = 0;
689}
690
691static inline void
Jonathan Kew798e4182014-06-10 13:10:30 +0100692zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
Behdad Esfahbodd785fa02013-05-20 09:18:52 -0400693{
694 unsigned int count = buffer->len;
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400695 hb_glyph_info_t *info = buffer->info;
Behdad Esfahbodd785fa02013-05-20 09:18:52 -0400696 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400697 if (_hb_glyph_info_is_mark (&info[i]))
Behdad Esfahbodd785fa02013-05-20 09:18:52 -0400698 {
Jonathan Kew798e4182014-06-10 13:10:30 +0100699 if (adjust_offsets)
700 adjust_mark_offsets (&buffer->pos[i]);
701 zero_mark_width (&buffer->pos[i]);
Behdad Esfahbodd785fa02013-05-20 09:18:52 -0400702 }
703}
704
705static inline void
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400706hb_ot_position_default (hb_ot_shape_context_t *c)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100707{
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200708 hb_direction_t direction = c->buffer->props.direction;
Behdad Esfahbod967240d2010-10-05 23:00:05 -0400709 unsigned int count = c->buffer->len;
Behdad Esfahbodac8cd512013-10-18 19:33:09 +0200710 hb_glyph_info_t *info = c->buffer->info;
711 hb_glyph_position_t *pos = c->buffer->pos;
Behdad Esfahbod56800022013-02-12 09:44:57 -0500712
Behdad Esfahbodbee901b2015-11-04 19:28:17 -0800713 if (HB_DIRECTION_IS_HORIZONTAL (direction))
714 {
Koji Ishii95333642018-08-01 13:01:08 +0900715 c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
716 &pos[0].x_advance, sizeof(pos[0]));
Behdad Esfahbod67a36a72015-11-26 18:48:42 -0500717 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
Behdad Esfahbod5bc28b52015-11-04 21:53:16 -0800718 if (c->font->has_glyph_h_origin_func ())
719 for (unsigned int i = 0; i < count; i++)
720 c->font->subtract_glyph_h_origin (info[i].codepoint,
721 &pos[i].x_offset,
722 &pos[i].y_offset);
Behdad Esfahbodbee901b2015-11-04 19:28:17 -0800723 }
724 else
725 {
Behdad Esfahbod79e21982018-08-06 09:45:17 -0700726 c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
727 &pos[0].y_advance, sizeof(pos[0]));
Behdad Esfahbodbee901b2015-11-04 19:28:17 -0800728 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod67a36a72015-11-26 18:48:42 -0500729 {
Behdad Esfahbod67a36a72015-11-26 18:48:42 -0500730 c->font->subtract_glyph_v_origin (info[i].codepoint,
731 &pos[i].x_offset,
732 &pos[i].y_offset);
733 }
Behdad Esfahbod56800022013-02-12 09:44:57 -0500734 }
Behdad Esfahbod49ef6302015-11-04 17:27:07 -0800735 if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
736 _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
Behdad Esfahbod4b011092013-09-13 20:17:42 -0400737}
738
Behdad Esfahbode2b87802016-12-22 14:40:19 -0600739static inline void
Behdad Esfahbod4b011092013-09-13 20:17:42 -0400740hb_ot_position_complex (hb_ot_shape_context_t *c)
741{
Behdad Esfahbod4b011092013-09-13 20:17:42 -0400742 unsigned int count = c->buffer->len;
Behdad Esfahbod9786fcd2017-10-03 17:22:43 +0200743 hb_glyph_info_t *info = c->buffer->info;
744 hb_glyph_position_t *pos = c->buffer->pos;
Behdad Esfahbod84742312016-02-11 16:27:41 +0700745
Jonathan Kew798e4182014-06-10 13:10:30 +0100746 /* If the font has no GPOS, AND, no fallback positioning will
747 * happen, AND, direction is forward, then when zeroing mark
748 * widths, we shift the mark with it, such that the mark
749 * is positioned hanging over the previous glyph. When
750 * direction is backward we don't shift and it will end up
751 * hanging over the next glyph after the final reordering.
752 * If fallback positinoing happens or GPOS is present, we don't
753 * care.
754 */
Behdad Esfahbod96eca872018-10-02 13:24:40 +0200755 bool adjust_offsets_when_zeroing = c->plan->fallback_positioning &&
Behdad Esfahbode2b87802016-12-22 14:40:19 -0600756 !c->plan->shaper->fallback_position &&
757 HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
Behdad Esfahbod56800022013-02-12 09:44:57 -0500758
Behdad Esfahbod9786fcd2017-10-03 17:22:43 +0200759 /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
760
761 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
762 if (c->font->has_glyph_h_origin_func ())
763 for (unsigned int i = 0; i < count; i++)
764 c->font->add_glyph_h_origin (info[i].codepoint,
765 &pos[i].x_offset,
766 &pos[i].y_offset);
767
768 hb_ot_layout_position_start (c->font, c->buffer);
769
Behdad Esfahbod71b4c992013-10-28 00:20:59 +0100770 switch (c->plan->shaper->zero_width_marks)
Behdad Esfahbod56800022013-02-12 09:44:57 -0500771 {
Behdad Esfahbod127daf12013-05-20 09:11:35 -0400772 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
Jonathan Kew798e4182014-06-10 13:10:30 +0100773 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
Behdad Esfahbod56800022013-02-12 09:44:57 -0500774 break;
775
776 default:
777 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
Behdad Esfahbod127daf12013-05-20 09:11:35 -0400778 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
Behdad Esfahbod56800022013-02-12 09:44:57 -0500779 break;
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100780 }
Behdad Esfahbodc86f9322011-07-25 00:44:50 -0400781
Behdad Esfahbod96eca872018-10-02 13:24:40 +0200782 if (likely (!c->plan->fallback_positioning))
Behdad Esfahbod8bb5deb2012-08-02 10:07:58 -0400783 c->plan->position (c->font, c->buffer);
Behdad Esfahbodc86f9322011-07-25 00:44:50 -0400784
Behdad Esfahbod71b4c992013-10-28 00:20:59 +0100785 switch (c->plan->shaper->zero_width_marks)
Behdad Esfahbod0291a652013-02-13 05:57:24 -0500786 {
Behdad Esfahbod127daf12013-05-20 09:11:35 -0400787 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
Jonathan Kew798e4182014-06-10 13:10:30 +0100788 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
Behdad Esfahbod127daf12013-05-20 09:11:35 -0400789 break;
790
Behdad Esfahbod0291a652013-02-13 05:57:24 -0500791 default:
792 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
Behdad Esfahbod127daf12013-05-20 09:11:35 -0400793 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
Behdad Esfahbod0291a652013-02-13 05:57:24 -0500794 break;
795 }
796
Behdad Esfahbod7d8d58a2016-02-11 16:34:28 +0700797 /* Finishing off GPOS has to follow a certain order. */
798 hb_ot_layout_position_finish_advances (c->font, c->buffer);
Behdad Esfahbod84742312016-02-11 16:27:41 +0700799 hb_ot_zero_width_default_ignorables (c);
Behdad Esfahbod7d8d58a2016-02-11 16:34:28 +0700800 hb_ot_layout_position_finish_offsets (c->font, c->buffer);
Behdad Esfahbod9786fcd2017-10-03 17:22:43 +0200801
802 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
803 if (c->font->has_glyph_h_origin_func ())
804 for (unsigned int i = 0; i < count; i++)
805 c->font->subtract_glyph_h_origin (info[i].codepoint,
806 &pos[i].x_offset,
807 &pos[i].y_offset);
Behdad Esfahbodc86f9322011-07-25 00:44:50 -0400808}
809
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400810static inline void
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400811hb_ot_position (hb_ot_shape_context_t *c)
812{
Behdad Esfahbod84742312016-02-11 16:27:41 +0700813 c->buffer->clear_positions ();
Behdad Esfahbod4b011092013-09-13 20:17:42 -0400814
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400815 hb_ot_position_default (c);
816
Behdad Esfahbode2b87802016-12-22 14:40:19 -0600817 hb_ot_position_complex (c);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400818
Behdad Esfahbod96eca872018-10-02 13:24:40 +0200819 if (c->plan->fallback_positioning && c->plan->shaper->fallback_position)
Behdad Esfahbod865745b2012-11-14 13:48:26 -0800820 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400821
822 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
823 hb_buffer_reverse (c->buffer);
824
Behdad Esfahbod865745b2012-11-14 13:48:26 -0800825 /* Visual fallback goes here. */
826
Behdad Esfahbod96eca872018-10-02 13:24:40 +0200827 if (c->plan->fallback_positioning)
Behdad Esfahbodba87b8f2013-02-21 15:23:39 -0500828 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
Behdad Esfahbod8f3eebf2014-08-02 17:18:46 -0400829
830 _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
Ebrahim Byagowi1ab16f42018-02-24 12:49:42 +0330831
832 //hb_aat_layout_position (c->font, c->buffer);
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400833}
834
Behdad Esfahbod1c17c2b2017-08-11 19:06:07 -0700835static inline void
836hb_propagate_flags (hb_buffer_t *buffer)
837{
838 /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
839 * Simplifies using them. */
840
841 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
842 return;
843
844 hb_glyph_info_t *info = buffer->info;
845
846 foreach_cluster (buffer, start, end)
847 {
848 unsigned int mask = 0;
849 for (unsigned int i = start; i < end; i++)
850 if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
851 {
852 mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
853 break;
854 }
855 if (mask)
856 for (unsigned int i = start; i < end; i++)
857 info[i].mask |= mask;
858 }
859}
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400860
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400861/* Pull it all together! */
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100862
Behdad Esfahbod967240d2010-10-05 23:00:05 -0400863static void
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400864hb_ot_shape_internal (hb_ot_shape_context_t *c)
Behdad Esfahbod967240d2010-10-05 23:00:05 -0400865{
Behdad Esfahbodb65c0602011-07-28 16:48:43 -0400866 c->buffer->deallocate_var_all ();
Behdad Esfahbod49ef6302015-11-04 17:27:07 -0800867 c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
Behdad Esfahbodbddeb2b2018-07-10 14:12:37 +0200868 if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
Behdad Esfahbod43017032015-11-05 23:44:59 -0800869 {
Behdad Esfahbodbaf77792017-11-14 21:53:48 -0800870 c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
Behdad Esfahbod43017032015-11-05 23:44:59 -0800871 (unsigned) HB_BUFFER_MAX_LEN_MIN);
872 }
Behdad Esfahbodbddeb2b2018-07-10 14:12:37 +0200873 if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
Behdad Esfahbodbaf77792017-11-14 21:53:48 -0800874 {
875 c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
876 (unsigned) HB_BUFFER_MAX_OPS_MIN);
877 }
Behdad Esfahbodb65c0602011-07-28 16:48:43 -0400878
Behdad Esfahbodd2ba0162010-10-12 15:35:45 -0400879 /* Save the original direction, we use it later. */
Behdad Esfahbodbbbbe802010-12-07 16:22:02 -0500880 c->target_direction = c->buffer->props.direction;
Behdad Esfahbodd2ba0162010-10-12 15:35:45 -0400881
Behdad Esfahbod101303d2013-10-18 00:42:39 +0200882 _hb_buffer_allocate_unicode_vars (c->buffer);
Behdad Esfahbodb65c0602011-07-28 16:48:43 -0400883
Behdad Esfahbod330a2af2012-06-08 20:40:02 -0400884 c->buffer->clear_output ();
885
Behdad Esfahbod7cc34802017-09-04 20:04:59 -0700886 hb_ot_shape_initialize_masks (c);
Behdad Esfahbodd1deaa22012-05-09 15:04:13 +0200887 hb_set_unicode_props (c->buffer);
Behdad Esfahbod6912e472012-09-01 20:38:45 -0400888 hb_insert_dotted_circle (c->buffer, c->font);
Behdad Esfahbod7cc34802017-09-04 20:04:59 -0700889
Behdad Esfahbod4ff0d2d2011-07-22 16:15:32 -0400890 hb_form_clusters (c->buffer);
891
Behdad Esfahbodaa726412011-07-21 11:34:59 -0400892 hb_ensure_native_direction (c->buffer);
Behdad Esfahbod54d1a0d2011-07-21 01:11:09 -0400893
Behdad Esfahbod13686332015-11-05 13:24:15 -0800894 if (c->plan->shaper->preprocess_text)
895 c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
896
Behdad Esfahbod5c60b702012-08-09 21:58:07 -0400897 hb_ot_substitute (c);
898 hb_ot_position (c);
Behdad Esfahbod655586f2011-07-21 00:51:18 -0400899
Behdad Esfahbod8cfbc302015-07-22 18:41:10 +0100900 hb_ot_hide_default_ignorables (c);
901
Behdad Esfahbod13686332015-11-05 13:24:15 -0800902 if (c->plan->shaper->postprocess_glyphs)
903 c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
904
Behdad Esfahbod1c17c2b2017-08-11 19:06:07 -0700905 hb_propagate_flags (c->buffer);
906
Behdad Esfahbod101303d2013-10-18 00:42:39 +0200907 _hb_buffer_deallocate_unicode_vars (c->buffer);
Behdad Esfahbodb65c0602011-07-28 16:48:43 -0400908
Behdad Esfahbodbbbbe802010-12-07 16:22:02 -0500909 c->buffer->props.direction = c->target_direction;
Behdad Esfahbod9f9bcce2011-07-28 17:06:46 -0400910
Behdad Esfahbod43017032015-11-05 23:44:59 -0800911 c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
Behdad Esfahbodbaf77792017-11-14 21:53:48 -0800912 c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
Behdad Esfahbod9f9bcce2011-07-28 17:06:46 -0400913 c->buffer->deallocate_var_all ();
Behdad Esfahbod967240d2010-10-05 23:00:05 -0400914}
915
Behdad Esfahbodfd3d32d2010-10-12 16:57:47 -0400916
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400917hb_bool_t
Behdad Esfahbodbd26b4d2012-07-26 22:05:39 -0400918_hb_ot_shape (hb_shape_plan_t *shape_plan,
919 hb_font_t *font,
Behdad Esfahbod6bd9b472012-04-12 14:53:53 -0400920 hb_buffer_t *buffer,
921 const hb_feature_t *features,
922 unsigned int num_features)
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100923{
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400924 hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
925 hb_ot_shape_internal (&c);
Behdad Esfahbod02aeca92011-08-04 22:31:05 -0400926
Behdad Esfahbod0594a242012-06-05 20:35:40 -0400927 return true;
Behdad Esfahbodca663bb2010-05-21 14:34:23 +0100928}
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400929
930
Sascha Brawer01c3a882015-06-01 13:22:01 +0200931/**
Behdad Esfahbod35d18582015-11-26 19:30:37 -0500932 * hb_ot_shape_plan_collect_lookups:
933 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200934 * Since: 0.9.7
935 **/
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800936void
937hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
938 hb_tag_t table_tag,
939 hb_set_t *lookup_indexes /* OUT */)
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400940{
Behdad Esfahbod51bb4982012-11-16 14:08:05 -0800941 /* XXX Does the first part always succeed? */
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800942 HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
Behdad Esfahbodb00321e2012-08-09 22:33:32 -0400943}
944
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800945
946/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
947static void
948add_char (hb_font_t *font,
949 hb_unicode_funcs_t *unicode,
950 hb_bool_t mirror,
951 hb_codepoint_t u,
952 hb_set_t *glyphs)
953{
954 hb_codepoint_t glyph;
Behdad Esfahbod8b5bc142016-02-24 19:05:23 +0900955 if (font->get_nominal_glyph (u, &glyph))
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800956 glyphs->add (glyph);
957 if (mirror)
958 {
959 hb_codepoint_t m = unicode->mirroring (u);
Behdad Esfahbod8b5bc142016-02-24 19:05:23 +0900960 if (m != u && font->get_nominal_glyph (m, &glyph))
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800961 glyphs->add (glyph);
962 }
963}
964
965
Sascha Brawer01c3a882015-06-01 13:22:01 +0200966/**
Behdad Esfahbod35d18582015-11-26 19:30:37 -0500967 * hb_ot_shape_glyphs_closure:
968 *
Sascha Brawer01c3a882015-06-01 13:22:01 +0200969 * Since: 0.9.2
970 **/
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400971void
972hb_ot_shape_glyphs_closure (hb_font_t *font,
973 hb_buffer_t *buffer,
974 const hb_feature_t *features,
975 unsigned int num_features,
976 hb_set_t *glyphs)
977{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200978 const char *shapers[] = {"ot", nullptr};
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800979 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
980 features, num_features, shapers);
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400981
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800982 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400983
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400984 unsigned int count = buffer->len;
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400985 hb_glyph_info_t *info = buffer->info;
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400986 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod7cd33f22014-07-17 14:22:11 -0400987 add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
Behdad Esfahbodf3064102012-11-15 18:39:46 -0800988
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400989 hb_set_t *lookups = hb_set_create ();
990 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
Garret Rieger57badad2018-06-06 16:02:51 -0700991 hb_ot_layout_lookups_substitute_closure (font->face, lookups, glyphs);
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400992
993 hb_set_destroy (lookups);
Behdad Esfahbode82061e2012-07-27 02:29:32 -0400994
995 hb_shape_plan_destroy (shape_plan);
Behdad Esfahbod1827dc22012-04-24 16:56:37 -0400996}