12014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009,2010  Red Hat, Inc.
307d682806349aee81f53114778ce0beb23909ed7Behdad Esfahbod * Copyright © 2010,2011,2012  Google, Inc.
42014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
62014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod *
72014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * Permission is hereby granted, without written agreement and without
82014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
92014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * software and its documentation for any purpose, provided that the
102014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
112014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * all copies of this software.
122014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod *
132014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
142014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
152014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
162014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
172014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * DAMAGE.
182014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod *
192014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
202014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
212014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
222014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
232014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
242014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod *
252014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
26476c94218b4f5b8e119e82b0e10b641e0c10bf56Behdad Esfahbod * Google Author(s): Behdad Esfahbod
272014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod */
282014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
29027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define HB_SHAPER ot
30027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define hb_ot_shaper_face_data_t hb_ot_layout_t
31e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
32027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-impl-private.hh"
33027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
344924affe0f0adf75f2a0e2137a71206b0576d63fBehdad Esfahbod#include "hb-ot-shape-private.hh"
3516c6a27b4bffc19026944c7bea9cf0a3a8ff1d8fBehdad Esfahbod#include "hb-ot-shape-complex-private.hh"
369c929abdcfef44c0193a2917b20981df37ade21cBehdad Esfahbod#include "hb-ot-shape-fallback-private.hh"
37affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod#include "hb-ot-shape-normalize-private.hh"
382014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
39b70021f7c81a0ed08475b14b07291f662cd9f905Behdad Esfahbod#include "hb-ot-layout-private.hh"
40878a25375b2fdf64cf0cc30c23fca9fcd58548e8Behdad Esfahbod#include "hb-unicode-private.hh"
411827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod#include "hb-set-private.hh"
4272657e4ce757dcb055a8db7291b68f96f0d34bfbBehdad Esfahbod
43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
44a02d86484be870615297abfc7be9f94645434762Behdad Esfahbodstatic hb_tag_t common_features[] = {
452014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  HB_TAG('c','c','m','p'),
46a5f1834f57ea3fb254f5c7d372747de316fcc8f1Behdad Esfahbod  HB_TAG('l','i','g','a'),
4789a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('l','o','c','l'),
4889a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('m','a','r','k'),
4989a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('m','k','m','k'),
5089a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('r','l','i','g'),
5189a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod};
5289a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod
53d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod
54a02d86484be870615297abfc7be9f94645434762Behdad Esfahbodstatic hb_tag_t horizontal_features[] = {
5589a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('c','a','l','t'),
562014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  HB_TAG('c','l','i','g'),
57bd0987386b3a4dddf208ccf1a70ebfff6242ba73Behdad Esfahbod  HB_TAG('c','u','r','s'),
582014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  HB_TAG('k','e','r','n'),
59f4e48adcdd4315ce09e755f87a0f801d88194f42Behdad Esfahbod  HB_TAG('r','c','l','t'),
6089a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod};
6189a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod
62a02d86484be870615297abfc7be9f94645434762Behdad Esfahbodstatic hb_tag_t vertical_features[] = {
6389a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  HB_TAG('v','e','r','t'),
642014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod};
652014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
66b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod
67b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod
682014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodstatic void
6990645fb24bcbb78183576d3641a99560d87e49f2Behdad Esfahbodhb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
7049baa1f69efb0e3c62e45bd59dd88459a84bf390Behdad Esfahbod			      const hb_segment_properties_t  *props,
7190645fb24bcbb78183576d3641a99560d87e49f2Behdad Esfahbod			      const hb_feature_t             *user_features,
7290645fb24bcbb78183576d3641a99560d87e49f2Behdad Esfahbod			      unsigned int                    num_user_features)
732014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
748bb5deba9630d35878eb6edb4643ecfabf99f15fBehdad Esfahbod  hb_ot_map_builder_t *map = &planner->map;
758bb5deba9630d35878eb6edb4643ecfabf99f15fBehdad Esfahbod
76895fb5d364e7ae5d9d2e34b9f68b8651804369efBehdad Esfahbod  switch (props->direction) {
770e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod    case HB_DIRECTION_LTR:
78e7ffcfafb1108801ac504f18f820e497226bf07fBehdad Esfahbod      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
79e7ffcfafb1108801ac504f18f820e497226bf07fBehdad Esfahbod      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
800e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod      break;
810e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod    case HB_DIRECTION_RTL:
82e7ffcfafb1108801ac504f18f820e497226bf07fBehdad Esfahbod      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
83ec5448667b30ad662401c2b4f5fc0da524c013fdBehdad Esfahbod      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
840e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod      break;
850e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod    case HB_DIRECTION_TTB:
860e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod    case HB_DIRECTION_BTT:
873286fc0e9adc3f2874c9409e7fdb09e4d2b7dda1Behdad Esfahbod    case HB_DIRECTION_INVALID:
880e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod    default:
890e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod      break;
900e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod  }
910e235d0fc9bdeeaffa7215c21abc5d40767a10c7Behdad Esfahbod
923aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
933aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
943aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
953aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
96693918ef8541014a5ef7dfb91c6ea0ae36d9c368Behdad Esfahbod  if (planner->shaper->collect_features)
9716c6a27b4bffc19026944c7bea9cf0a3a8ff1d8fBehdad Esfahbod    planner->shaper->collect_features (planner);
98e04685ee7be01695ec437fab50f919f1b7423c57Behdad Esfahbod
99ee9c3a17d0bf263c5eee479fd778db97cff8e189Behdad Esfahbod  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
100ee9c3a17d0bf263c5eee479fd778db97cff8e189Behdad Esfahbod    map->add_global_bool_feature (common_features[i]);
10189a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod
10289a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
103ee9c3a17d0bf263c5eee479fd778db97cff8e189Behdad Esfahbod    for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
104038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
105038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod			(horizontal_features[i] == HB_TAG('k','e','r','n') ?
106038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod			 F_HAS_FALLBACK : F_NONE));
10789a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod  else
108ee9c3a17d0bf263c5eee479fd778db97cff8e189Behdad Esfahbod    for (unsigned int i = 0; i < ARRAY_LENGTH (vertical_features); i++)
109038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod      map->add_feature (vertical_features[i], 1, F_GLOBAL |
110038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod			(vertical_features[i] == HB_TAG('v','k','r','n') ?
111038c98f6866fe1177b04bd2ae3bb461b2f0fd1edBehdad Esfahbod			 F_HAS_FALLBACK : F_NONE));
11289a2bc9ba674e7e57fec1fd8ce7648a44f3aab63Behdad Esfahbod
113693918ef8541014a5ef7dfb91c6ea0ae36d9c368Behdad Esfahbod  if (planner->shaper->override_features)
11416c6a27b4bffc19026944c7bea9cf0a3a8ff1d8fBehdad Esfahbod    planner->shaper->override_features (planner);
115d96838ef951ce6170eb2dc576ebcba2262cf7008Behdad Esfahbod
116895fb5d364e7ae5d9d2e34b9f68b8651804369efBehdad Esfahbod  for (unsigned int i = 0; i < num_user_features; i++) {
117895fb5d364e7ae5d9d2e34b9f68b8651804369efBehdad Esfahbod    const hb_feature_t *feature = &user_features[i];
118ec5448667b30ad662401c2b4f5fc0da524c013fdBehdad Esfahbod    map->add_feature (feature->tag, feature->value,
119ec5448667b30ad662401c2b4f5fc0da524c013fdBehdad Esfahbod		      (feature->start == 0 && feature->end == (unsigned int) -1) ?
120ec5448667b30ad662401c2b4f5fc0da524c013fdBehdad Esfahbod		       F_GLOBAL : F_NONE);
121e04685ee7be01695ec437fab50f919f1b7423c57Behdad Esfahbod  }
122e89b7d2a61b7f58e6c7cec00d5ce2246dee1e8a1Behdad Esfahbod}
123e89b7d2a61b7f58e6c7cec00d5ce2246dee1e8a1Behdad Esfahbod
124e89b7d2a61b7f58e6c7cec00d5ce2246dee1e8a1Behdad Esfahbod
125e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod/*
126e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod * shaper face data
127e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod */
128e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
129e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodhb_ot_shaper_face_data_t *
130e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod_hb_ot_shaper_face_data_create (hb_face_t *face)
131e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
132e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  return _hb_ot_layout_create (face);
133e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
134e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
135e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodvoid
136e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
137e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
138e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  _hb_ot_layout_destroy (data);
139e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
140e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
141e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
142e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod/*
143e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod * shaper font data
144e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod */
145e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
146e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodstruct hb_ot_shaper_font_data_t {};
147e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
148e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodhb_ot_shaper_font_data_t *
149e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod_hb_ot_shaper_font_data_create (hb_font_t *font)
150e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
151e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
152e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
153e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
154e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodvoid
155e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
156e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
157e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
158e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
159e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
160e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod/*
161e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod * shaper shape_plan data
162e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod */
163e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
164e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodhb_ot_shaper_shape_plan_data_t *
165e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
166e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod				      const hb_feature_t *user_features,
167e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod				      unsigned int        num_user_features)
168e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
169a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
170a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  if (unlikely (!plan))
171e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod    return NULL;
172e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
1735393e3a62ba09fd7bcf3767b36225c8f49badb9dBehdad Esfahbod  hb_ot_shape_planner_t planner (shape_plan);
174e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
1759b37b4c5800b158f61602d2aba8a01349e24d251Behdad Esfahbod  planner.shaper = hb_ot_shape_complex_categorize (&planner);
176e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
177e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
178e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
179a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  planner.compile (*plan);
180e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
181a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  if (plan->shaper->data_create) {
182a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod    plan->data = plan->shaper->data_create (plan);
183a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod    if (unlikely (!plan->data))
184a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod      return NULL;
185a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  }
186a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod
187a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  return plan;
188e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
189e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
190e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodvoid
191a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
192e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod{
193a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  if (plan->shaper->data_destroy)
194a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod    plan->shaper->data_destroy (const_cast<void *> (plan->data));
195a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod
196a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  plan->finish ();
1974ba647eecf0f70917ac4229af1f2dd3c62fcb7d5Behdad Esfahbod
198a8c6da90f4c6e8d27a3a1b758a55476776d9f750Behdad Esfahbod  free (plan);
199e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod}
200e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
201e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
202e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod/*
203e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod * shaper
204e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod */
205e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
206b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbodstruct hb_ot_shape_context_t
207b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod{
208b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  hb_ot_shape_plan_t *plan;
209b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  hb_font_t *font;
210b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  hb_face_t *face;
211b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  hb_buffer_t  *buffer;
212b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  const hb_feature_t *user_features;
213b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  unsigned int        num_user_features;
214b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod
215b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  /* Transient stuff */
216b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod  hb_direction_t target_direction;
217b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod};
218b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbod
2192014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2202014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
221ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod/* Main shaper */
222ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
2235c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
224ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod/* Prepare */
225ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
226b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbodstatic void
227b9f199c8e38cc5ed0d73845568630f3bcbdd4374Behdad Esfahbodhb_set_unicode_props (hb_buffer_t *buffer)
2283a852ae7fe6edfaadd75625d27515a3689503395Behdad Esfahbod{
229aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod  unsigned int count = buffer->len;
2307cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
2310e3361464b00b76aa7375515163e0710a691db0cBehdad Esfahbod  for (unsigned int i = 0; i < count; i++)
2327cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode);
2333a852ae7fe6edfaadd75625d27515a3689503395Behdad Esfahbod}
2343a852ae7fe6edfaadd75625d27515a3689503395Behdad Esfahbod
2353a852ae7fe6edfaadd75625d27515a3689503395Behdad Esfahbodstatic void
2366912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbodhb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
2376912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod{
2380c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbod  if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
239f2eb3fa9dca8d21fae20c9b9dddad3245df74a05Behdad Esfahbod      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
2406912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
2416912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod    return;
2426912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2437627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod  if (!font->has_glyph (0x25CCu))
2446912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod    return;
2456912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2466912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  hb_glyph_info_t dottedcircle;
2477627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod  dottedcircle.codepoint = 0x25CCu;
2486912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
2496912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2506912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  buffer->clear_output ();
2516912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2526912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  buffer->idx = 0;
2536912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  hb_glyph_info_t info = dottedcircle;
2546912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  info.cluster = buffer->cur().cluster;
2556912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  info.mask = buffer->cur().mask;
2566912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  buffer->output_info (info);
2576912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  while (buffer->idx < buffer->len)
2586912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod    buffer->next_glyph ();
2596912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2606912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  buffer->swap_buffers ();
2616912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod}
2626912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod
2636912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbodstatic void
264aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbodhb_form_clusters (hb_buffer_t *buffer)
265ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
266aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod  unsigned int count = buffer->len;
2677cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
268ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  for (unsigned int i = 1; i < count; i++)
2697cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))
270330a2af3ff0e12c01b3b451357b8bdc83b2e9b47Behdad Esfahbod      buffer->merge_clusters (i - 1, i + 1);
271ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
272ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
273967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbodstatic void
274aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbodhb_ensure_native_direction (hb_buffer_t *buffer)
275ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
276aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod  hb_direction_t direction = buffer->props.direction;
277ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
2787403e055cd1463f38215ad9faedd61c3e1b66ac5Behdad Esfahbod  /* TODO vertical:
2797403e055cd1463f38215ad9faedd61c3e1b66ac5Behdad Esfahbod   * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
2807403e055cd1463f38215ad9faedd61c3e1b66ac5Behdad Esfahbod   * Ogham fonts are supposed to be implemented BTT or not.  Need to research that
2817403e055cd1463f38215ad9faedd61c3e1b66ac5Behdad Esfahbod   * first. */
282aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod  if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
2837403e055cd1463f38215ad9faedd61c3e1b66ac5Behdad Esfahbod      (HB_DIRECTION_IS_VERTICAL   (direction) && direction != HB_DIRECTION_TTB))
284ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  {
285aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod    hb_buffer_reverse_clusters (buffer);
286aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod    buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
287ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  }
288ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
289ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
290ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
291ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod/* Substitute */
292ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
2935c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
2945c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodhb_ot_mirror_chars (hb_ot_shape_context_t *c)
295ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
296bbbbe80ec9bc45c5b685bc09c8f993e98496555cBehdad Esfahbod  if (HB_DIRECTION_IS_FORWARD (c->target_direction))
297ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod    return;
298ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
299ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
300ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_unicode_funcs_t *unicode = buffer->unicode;
3015497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod  hb_mask_t rtlm_mask = c->plan->rtlm_mask;
3024e4ef24e46f273ad2bdda2f718223e05b37dd50fBehdad Esfahbod
303ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  unsigned int count = buffer->len;
304ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
305ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  for (unsigned int i = 0; i < count; i++) {
306ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
307ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    if (likely (codepoint == info[i].codepoint))
308ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      info[i].mask |= rtlm_mask;
3091094a294f6a44c47fc75867983f2b135a6442babBehdad Esfahbod    else
310ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      info[i].codepoint = codepoint;
311ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  }
312ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
313ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
3145c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
3153aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbodhb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
3163aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod{
3175497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod  if (!c->plan->has_frac)
3185497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod    return;
3195497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod
3203aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  hb_buffer_t *buffer = c->buffer;
3213aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
3223aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  /* TODO look in pre/post context text also. */
3233aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  unsigned int count = buffer->len;
3243aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  hb_glyph_info_t *info = buffer->info;
3253aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  for (unsigned int i = 0; i < count; i++)
3263aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  {
3277627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod    if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
3283aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod    {
3293aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod      unsigned int start = i, end = i + 1;
3303aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod      while (start &&
3313aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod	     _hb_glyph_info_get_general_category (&info[start - 1]) ==
3323aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
3333aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod        start--;
3343aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod      while (end < count &&
3353aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod	     _hb_glyph_info_get_general_category (&info[end]) ==
3363aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
3373aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod        end++;
3383aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
339a7e8bbb080aef318b16750ca1771d0d3af3d0ae9Behdad Esfahbod      for (unsigned int j = start; j < i; j++)
3405497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod        info[j].mask |= c->plan->numr_mask | c->plan->frac_mask;
3415497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod      info[i].mask |= c->plan->frac_mask;
342a7e8bbb080aef318b16750ca1771d0d3af3d0ae9Behdad Esfahbod      for (unsigned int j = i + 1; j < end; j++)
3435497a8a274a7066c0230c850baadef681785c8bbBehdad Esfahbod        info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask;
3443aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
3453aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod      i = end - 1;
3463aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod    }
3473aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  }
3483aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod}
3493aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
3503aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbodstatic inline void
351739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbodhb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
3525c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod{
3535c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_map_t *map = &c->plan->map;
354ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
3555c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
3565c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_mask_t global_mask = map->get_global_mask ();
357ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  buffer->reset_masks (global_mask);
358739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod}
359739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod
360739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbodstatic inline void
361739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbodhb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
362739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod{
363739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod  hb_ot_map_t *map = &c->plan->map;
364739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
3655c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
3663aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod  hb_ot_shape_setup_masks_fraction (c);
3673aeee519f0b82df5263974945ae852badc4dbdedBehdad Esfahbod
3685c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  if (c->plan->shaper->setup_masks)
369ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    c->plan->shaper->setup_masks (c->plan, buffer, c->font);
3705c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
3715c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  for (unsigned int i = 0; i < c->num_user_features; i++)
3725c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  {
3735c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod    const hb_feature_t *feature = &c->user_features[i];
3745c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod    if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
3755c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod      unsigned int shift;
3765c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod      hb_mask_t mask = map->get_mask (feature->tag, &shift);
377ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
3785c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod    }
3795c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  }
3805c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod}
3815c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
3825c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
383b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbodhb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
384ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
385b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod  /* Normalization process sets up glyph_index(), we just copy it. */
386b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod  unsigned int count = buffer->len;
3877cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
388b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod  for (unsigned int i = 0; i < count; i++)
3897cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    info[i].codepoint = info[i].glyph_index();
390ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
391ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
3925c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
3930ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbodhb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
3940ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbod{
3950ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbod  unsigned int count = c->buffer->len;
396ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_glyph_info_t *info = c->buffer->info;
3970ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
398ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod  {
399ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod    hb_ot_layout_glyph_class_mask_t klass;
400ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod
4013b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod    /* Never mark default-ignorables as marks.
4023b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * They won't get in the way of lookups anyway,
4033b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * but having them as mark will cause them to be skipped
4043b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * over if the lookup-flag says so, but at least for the
4053b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * Mongolian variation selectors, looks like Uniscribe
4063b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * marks them as non-mark.  Some Mongolian fonts without
4073b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * GDEF rely on this.  Another notable character that
4083b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod     * this applies to is COMBINING GRAPHEME JOINER. */
4093b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
4103b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod	     HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
4113b861421a772f52eb232ff93bd74b5a8214801ecBehdad Esfahbod	     _hb_glyph_info_is_default_ignorable (&info[i])) ?
412ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod	    HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
413ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod	    HB_OT_LAYOUT_GLYPH_PROPS_MARK;
414ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod    _hb_glyph_info_set_glyph_props (&info[i], klass);
415ec181e50140fc65b32d6080e2f7f73bbe0269ba9Behdad Esfahbod  }
4160ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbod}
4170ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbod
4180ccf9b64736559a230425fd131c9eb8aa3048221Behdad Esfahbodstatic inline void
4195c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodhb_ot_substitute_default (hb_ot_shape_context_t *c)
420ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
421ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
422ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod
423fabd3113a98c5f4114f48920fa7ea38bd65a8d32Behdad Esfahbod  if (c->plan->shaper->preprocess_text)
424ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    c->plan->shaper->preprocess_text (c->plan, buffer, c->font);
4259f9f04c2229227bb0712166e824157bbbf5cef80Behdad Esfahbod
426739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod  hb_ot_shape_initialize_masks (c);
427739325178aba00ea5526c6a54ce588a79e5d45e2Behdad Esfahbod
4285c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_mirror_chars (c);
4295c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
430ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
431b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod
432ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  _hb_ot_shape_normalize (c->plan, buffer, c->font);
4335c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
4345c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_shape_setup_masks (c);
435b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod
4363992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod  /* This is unfortunate to go here, but necessary... */
4373992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod  if (!hb_ot_layout_has_positioning (c->face))
438ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
4393992b5ec4cb43d114d87ff7ee2b992bcf819c9cdBehdad Esfahbod
440ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_ot_map_glyphs_fast (buffer);
441b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod
442ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
443ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
444ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
4455c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
446c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbodhb_ot_substitute_complex (hb_ot_shape_context_t *c)
447c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod{
448ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
449ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod
450ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_ot_layout_substitute_start (c->font, buffer);
45105bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod
4525fecd8b0355894ceda14b3d3c654f20c3d5e77f4Behdad Esfahbod  if (!hb_ot_layout_has_glyph_classes (c->face))
4535fecd8b0355894ceda14b3d3c654f20c3d5e77f4Behdad Esfahbod    hb_synthesize_glyph_classes (c);
4545fecd8b0355894ceda14b3d3c654f20c3d5e77f4Behdad Esfahbod
455ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  c->plan->substitute (c->font, buffer);
456c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
457ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_ot_layout_substitute_finish (c->font, buffer);
458c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
459c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod  return;
460c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod}
461c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
4625c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
4635c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodhb_ot_substitute (hb_ot_shape_context_t *c)
4645c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod{
4655c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_substitute_default (c);
4665c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_substitute_complex (c);
4675c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod}
468ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
469ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod/* Position */
470ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
4715c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
472798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewadjust_mark_offsets (hb_glyph_position_t *pos)
473798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew{
474798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  pos->x_offset -= pos->x_advance;
475798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  pos->y_offset -= pos->y_advance;
476798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew}
477798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew
478798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewstatic inline void
479798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewzero_mark_width (hb_glyph_position_t *pos)
480798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew{
481798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  pos->x_advance = 0;
482798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  pos->y_advance = 0;
483798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew}
484798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew
485798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewstatic inline void
486798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewzero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
487d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod{
488d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod  unsigned int count = buffer->len;
4897cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
490d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
4917cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
492d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod    {
493798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      if (adjust_offsets)
494798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew        adjust_mark_offsets (&buffer->pos[i]);
495798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_width (&buffer->pos[i]);
496d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod    }
497d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod}
498d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod
499d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbodstatic inline void
500798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kewzero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
501d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod{
502d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod  unsigned int count = buffer->len;
5037cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
504d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
5057cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    if (_hb_glyph_info_is_mark (&info[i]))
506d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod    {
507798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      if (adjust_offsets)
508798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew        adjust_mark_offsets (&buffer->pos[i]);
509798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_width (&buffer->pos[i]);
510d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod    }
511d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod}
512d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbod
513d785fa0c45f7f25f5e5f352b933a5f6fa29be5c0Behdad Esfahbodstatic inline void
5145c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodhb_ot_position_default (hb_ot_shape_context_t *c)
515ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
516ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_direction_t direction = c->buffer->props.direction;
517967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbod  unsigned int count = c->buffer->len;
518ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_glyph_info_t *info = c->buffer->info;
519ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_glyph_position_t *pos = c->buffer->pos;
520568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
521568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  {
522ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    c->font->get_glyph_advance_for_direction (info[i].codepoint,
523ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod					      direction,
524ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod					      &pos[i].x_advance,
525ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod					      &pos[i].y_advance);
526ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
527ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod						  direction,
528ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod						  &pos[i].x_offset,
529ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod						  &pos[i].y_offset);
530568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod
531568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  }
5324b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod}
5334b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod
5344b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbodstatic inline bool
5354b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbodhb_ot_position_complex (hb_ot_shape_context_t *c)
5364b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod{
5374b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod  bool ret = false;
5384b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod  unsigned int count = c->buffer->len;
539798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  bool has_positioning = hb_ot_layout_has_positioning (c->face);
540798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  /* If the font has no GPOS, AND, no fallback positioning will
541798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * happen, AND, direction is forward, then when zeroing mark
542798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * widths, we shift the mark with it, such that the mark
543798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * is positioned hanging over the previous glyph.  When
544798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * direction is backward we don't shift and it will end up
545798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * hanging over the next glyph after the final reordering.
546798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * If fallback positinoing happens or GPOS is present, we don't
547798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   * care.
548798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew   */
549798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
550798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew                                       HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
551568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod
55271b4c999a511bf018acaf48a45e070470c0daf12Behdad Esfahbod  switch (c->plan->shaper->zero_width_marks)
553568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  {
554127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
555798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
556568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod      break;
557568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod
558127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    /* Not currently used for any shaper:
559127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
560798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
561127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod      break;
562127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    */
563127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod
564568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod    default:
565568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
566127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
567127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
568568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod      break;
569ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod  }
570c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
571798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew  if (has_positioning)
572b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod  {
573ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    hb_glyph_info_t *info = c->buffer->info;
574ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    hb_glyph_position_t *pos = c->buffer->pos;
575ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod
576b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod    /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
577b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod
578b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod    for (unsigned int i = 0; i < count; i++) {
579ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      c->font->add_glyph_origin_for_direction (info[i].codepoint,
5808fbfda920e0b3bb4ab7afb732826026964b79be9Behdad Esfahbod					       HB_DIRECTION_LTR,
581ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod					       &pos[i].x_offset,
582ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod					       &pos[i].y_offset);
583b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod    }
584c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
5858bb5deba9630d35878eb6edb4643ecfabf99f15fBehdad Esfahbod    c->plan->position (c->font, c->buffer);
586c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
587b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod    for (unsigned int i = 0; i < count; i++) {
588ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
5898fbfda920e0b3bb4ab7afb732826026964b79be9Behdad Esfahbod						    HB_DIRECTION_LTR,
590ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod						    &pos[i].x_offset,
591ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod						    &pos[i].y_offset);
592b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod    }
5932118fdb9f584e6735e904638e48bae48314372faBehdad Esfahbod
5945c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod    ret = true;
595affaf8a0e5aa38e5820455f789eebf916e02eb7bBehdad Esfahbod  }
5962bc3b9a616cedbc56ff4a915f9e3439ff3a6bf13Behdad Esfahbod
59771b4c999a511bf018acaf48a45e070470c0daf12Behdad Esfahbod  switch (c->plan->shaper->zero_width_marks)
5980291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod  {
599127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
600798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
6010291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod      break;
6020291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod
603127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
604798e4185bc71b1a63528e6b0af236d4c964ec607Jonathan Kew      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
605127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod      break;
606127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod
6070291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod    default:
6080291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
609127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
610127daf15e0b2f509ebd29a104236c8b38884efb0Behdad Esfahbod    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
6110291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod      break;
6120291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod  }
6130291a6528685f1f593707655943fb2360579cb9eBehdad Esfahbod
6145c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  return ret;
615c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod}
616c86f932015bdf5803572b0904d343d3bc033e009Behdad Esfahbod
6175c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodstatic inline void
6185c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbodhb_ot_position (hb_ot_shape_context_t *c)
6195c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod{
6204b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod  hb_ot_layout_position_start (c->font, c->buffer);
6214b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod
6225c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_position_default (c);
6235c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
6245c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_bool_t fallback = !hb_ot_position_complex (c);
6255c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
6264b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod  hb_ot_layout_position_finish (c->font, c->buffer);
6274b011094d5e90cf93df2891e47aeab1bffad5bbfBehdad Esfahbod
628865745b5b87236651f5663cae3461db9cb505eedBehdad Esfahbod  if (fallback && c->plan->shaper->fallback_position)
629865745b5b87236651f5663cae3461db9cb505eedBehdad Esfahbod    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
6305c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
6315c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
6325c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod    hb_buffer_reverse (c->buffer);
6335c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
634865745b5b87236651f5663cae3461db9cb505eedBehdad Esfahbod  /* Visual fallback goes here. */
635865745b5b87236651f5663cae3461db9cb505eedBehdad Esfahbod
6365c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  if (fallback)
637ba87b8fc89bf745068ccd19264a2631ea0904846Behdad Esfahbod    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
638ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
639ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
6405c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
6415c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod/* Post-process */
6425c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod
643d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbodstatic void
6440c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbodhb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
645d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod{
6460c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbod  if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
6470c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbod    return;
6480c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbod
6493d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  hb_codepoint_t space;
6503d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  enum {
6513d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    SPACE_DONT_KNOW,
6523d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    SPACE_AVAILABLE,
6533d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    SPACE_UNAVAILABLE
6543d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  } space_status = SPACE_DONT_KNOW;
655d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod
656d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod  unsigned int count = c->buffer->len;
6573d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  hb_glyph_info_t *info = c->buffer->info;
6583d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  hb_glyph_position_t *pos = c->buffer->pos;
6593d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  unsigned int j = 0;
660d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod  for (unsigned int i = 0; i < count; i++)
6613d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  {
662a1f7b2856184959e965c9c2b80363f9f46d486a7Behdad Esfahbod    if (unlikely (!_hb_glyph_info_ligated (&info[i]) &&
6633d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod		  _hb_glyph_info_is_default_ignorable (&info[i])))
664784f29d061a2939562eca0c4943feb01174aee00Behdad Esfahbod    {
6653d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      if (space_status == SPACE_DONT_KNOW)
6663d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod	space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : SPACE_UNAVAILABLE;
6673d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod
6683d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      if (space_status == SPACE_AVAILABLE)
6693d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      {
6703d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod	info[i].codepoint = space;
6713d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod	pos[i].x_advance = 0;
6723d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod	pos[i].y_advance = 0;
673784f29d061a2939562eca0c4943feb01174aee00Behdad Esfahbod      }
6743d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      else
6753d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod	continue; /* Delete it. */
6763d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    }
6773d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    if (j != i)
6783d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    {
6793d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      info[j] = info[i];
6803d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod      pos[j] = pos[i];
681d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod    }
6823d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod    j++;
6833d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  }
6843d2c4f0c2ff8fab4262988aad65b170e5b479b20Behdad Esfahbod  c->buffer->len = j;
685d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod}
686d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod
687ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
6885c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod/* Pull it all together! */
689ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
690967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbodstatic void
691e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbodhb_ot_shape_internal (hb_ot_shape_context_t *c)
692ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod{
693b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod  c->buffer->deallocate_var_all ();
694b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod
695d2ba016ca1ba7489537768b619980d5159b5870cBehdad Esfahbod  /* Save the original direction, we use it later. */
696bbbbe80ec9bc45c5b685bc09c8f993e98496555cBehdad Esfahbod  c->target_direction = c->buffer->props.direction;
697d2ba016ca1ba7489537768b619980d5159b5870cBehdad Esfahbod
698101303dbf7cf15d044bf2518f14b3aec65970feaBehdad Esfahbod  _hb_buffer_allocate_unicode_vars (c->buffer);
699b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod
700330a2af3ff0e12c01b3b451357b8bdc83b2e9b47Behdad Esfahbod  c->buffer->clear_output ();
701330a2af3ff0e12c01b3b451357b8bdc83b2e9b47Behdad Esfahbod
702d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod  hb_set_unicode_props (c->buffer);
7036912e476dd92639c3ddf07ca51c8d4a262c8b3a5Behdad Esfahbod  hb_insert_dotted_circle (c->buffer, c->font);
7044ff0d2d9dfc4f7e4880a4e964ca9872624508ea0Behdad Esfahbod  hb_form_clusters (c->buffer);
7054ff0d2d9dfc4f7e4880a4e964ca9872624508ea0Behdad Esfahbod
706aa7264123a088936f2043b45d4d41ca7413fabe5Behdad Esfahbod  hb_ensure_native_direction (c->buffer);
70754d1a0d2b2c4ffe15494967122c6422ecb1fc80bBehdad Esfahbod
7085c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_substitute (c);
7095c60b70c89b4e0a6512d9fd1ab5394dd76feb742Behdad Esfahbod  hb_ot_position (c);
710ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod
7110c7df2222862122ebbdc8665a21d6771ef5e0252Behdad Esfahbod  hb_ot_hide_default_ignorables (c);
712d1deaa2f5bd028e8076265cba92cffa4fa2834acBehdad Esfahbod
713101303dbf7cf15d044bf2518f14b3aec65970feaBehdad Esfahbod  _hb_buffer_deallocate_unicode_vars (c->buffer);
714b65c06025d2b54a44f716e030d4b10072c65bea8Behdad Esfahbod
715bbbbe80ec9bc45c5b685bc09c8f993e98496555cBehdad Esfahbod  c->buffer->props.direction = c->target_direction;
7169f9bcceca6321d5a5812f878de1de39901349a78Behdad Esfahbod
7179f9bcceca6321d5a5812f878de1de39901349a78Behdad Esfahbod  c->buffer->deallocate_var_all ();
718967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbod}
719967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbod
720fd3d32d31cb6d74a9994b6850d539fd0b707d941Behdad Esfahbod
72102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
722bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod_hb_ot_shape (hb_shape_plan_t    *shape_plan,
723bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod	      hb_font_t          *font,
7246bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod	      hb_buffer_t        *buffer,
7256bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod	      const hb_feature_t *features,
7266bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod	      unsigned int        num_features)
727967240dd8b96802345ef273e75427066e91ea8fbBehdad Esfahbod{
728e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
729e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_ot_shape_internal (&c);
73002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
7310594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
732ca663bb23c16f6a1f04efa6e10dad0e3e7c260a3Behdad Esfahbod}
7331827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
7341827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
735f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodvoid
736f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodhb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
737f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_tag_t         table_tag,
738f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_set_t        *lookup_indexes /* OUT */)
739f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod{
74051bb498b7b07bff4a447405b72f09b68d07a3e95Behdad Esfahbod  /* XXX Does the first part always succeed? */
741f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
742f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod}
743b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod
744f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod
745f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
746f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodstatic void
747f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodadd_char (hb_font_t          *font,
748f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod	  hb_unicode_funcs_t *unicode,
749f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod	  hb_bool_t           mirror,
750f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod	  hb_codepoint_t      u,
751f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod	  hb_set_t           *glyphs)
752b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod{
753f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  hb_codepoint_t glyph;
754f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  if (font->get_glyph (u, 0, &glyph))
755f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod    glyphs->add (glyph);
756f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  if (mirror)
757f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  {
758f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod    hb_codepoint_t m = unicode->mirroring (u);
759f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod    if (m != u && font->get_glyph (m, 0, &glyph))
760f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod      glyphs->add (glyph);
761f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  }
762b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod}
763b00321ea78793d9b3592b5173a9800e6322424feBehdad Esfahbod
764f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod
7651827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbodvoid
7661827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbodhb_ot_shape_glyphs_closure (hb_font_t          *font,
7671827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod			    hb_buffer_t        *buffer,
7681827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod			    const hb_feature_t *features,
7691827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod			    unsigned int        num_features,
7701827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod			    hb_set_t           *glyphs)
7711827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod{
7721827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  hb_ot_shape_plan_t plan;
7731827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
774f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  const char *shapers[] = {"ot", NULL};
775f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
776f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod							     features, num_features, shapers);
7771827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
778f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
7791827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
7801827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  unsigned int count = buffer->len;
7817cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod  hb_glyph_info_t *info = buffer->info;
7821827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
7837cd33f230441093dbfb1fec48f8c580ee8d9ef71Behdad Esfahbod    add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
784f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod
785f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  hb_set_t lookups;
786f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  lookups.init ();
787f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod  hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups);
7881827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod
7891827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  /* And find transitive closure. */
7901827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  hb_set_t copy;
7911827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  copy.init ();
7921827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod  do {
7931827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod    copy.set (glyphs);
794f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod    for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index);)
795f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod      hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
796aec89de5641fbe1c3031d63dd5f40ec99bf2a538Behdad Esfahbod  } while (!copy.is_equal (glyphs));
797e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod
798e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_shape_plan_destroy (shape_plan);
7991827dc208c867e433a95237d1ed3fc7a73d1d9a7Behdad Esfahbod}
800