hb-ot-layout.cc revision bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7
1fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 1998-2004  David Turner and Werner Lemberg
32409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2006  Behdad Esfahbod
42409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009  Red Hat, Inc.
5f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod * Copyright © 2012  Google, Inc.
6fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
7c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
8fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
9fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * Permission is hereby granted, without written agreement and without
10fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
11fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * software and its documentation for any purpose, provided that the
12fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * above copyright notice and the following two paragraphs appear in
13fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * all copies of this software.
14fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
15fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
16fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
17fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
18fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
19fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * DAMAGE.
20fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
21fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
22fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
24fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
25fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
26fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
27fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
28f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod * Google Author(s): Behdad Esfahbod
29fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod */
30fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
3122da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-ot-layout-private.hh"
32fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
337a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gdef-table.hh"
347a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gsub-table.hh"
357a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gpos-table.hh"
36fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
37d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod#include "hb-ot-map-private.hh"
38d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
39fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include <stdlib.h>
40aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod#include <string.h>
41aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
42acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
43cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
4411f4c87d01924cac43bf40044f67838440e19e42Behdad Esfahbod
450a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbodhb_ot_layout_t *
46266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_create (hb_face_t *face)
474a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
480a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
493dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod  if (unlikely (!layout))
503dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod    return NULL;
51555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod
527c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
537c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
5470e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
557c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
567c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
5770e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
587c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
597c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
600a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod
616f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
626f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
636f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod
6445fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
6545fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
661336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
6745fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
6845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod		(layout->gpos_lookup_count && !layout->gpos_accels)))
691336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  {
701336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    _hb_ot_layout_destroy (layout);
711336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    return NULL;
721336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  }
731336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
746f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
7545fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
766f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
7745fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
781336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
790a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return layout;
80f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
81f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
8223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
83266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_destroy (hb_ot_layout_t *layout)
84fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
8570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gdef_blob);
8670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gsub_blob);
8770e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gpos_blob);
88679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod
8945fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
9045fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gsub_accels[i].fini (layout->gsub->get_lookup (i));
9145fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
9245fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gpos_accels[i].fini (layout->gpos->get_lookup (i));
9345fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod
9445fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gsub_accels);
9545fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gpos_accels);
961336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
979ea7368fce3fa373d8d2925961ad211f5cf6ce70Behdad Esfahbod  free (layout);
9823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
99f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
1007c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GDEF&
10123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
10223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
1037c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
104ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gdef;
10523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
1067c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GSUB&
10723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
108fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
1097c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
110ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gsub;
111fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
1127c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GPOS&
11323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
1142ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
1157c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
116ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gpos;
1172ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
1182ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
11923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
120590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
121590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
122590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
123590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
124590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
12552ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
126590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
12723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
128590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
129590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
1305a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_glyph_class_t
1315a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
1325a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod			      hb_codepoint_t  glyph)
1335a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod{
1345a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
1355a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod}
1364a2d844c2f12dc1b858ab4ddd737ded7c0852221Behdad Esfahbod
13789ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodvoid
13889ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodhb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
13989ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_ot_layout_glyph_class_t  klass,
14089ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_set_t                   *glyphs /* OUT */)
14189ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod{
14289ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
14389ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod}
14489ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod
145e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
1460ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_attach_points (hb_face_t      *face,
14779420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				hb_codepoint_t  glyph,
148e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int    start_offset,
14979420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_count /* IN/OUT */,
15079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_array /* OUT */)
15179420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod{
152e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
15362964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod}
15462964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod
155e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
156e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbodhb_ot_layout_get_ligature_carets (hb_font_t      *font,
157e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_direction_t  direction,
158e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_codepoint_t  glyph,
159e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int    start_offset,
160e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int   *caret_count /* IN/OUT */,
161e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  int            *caret_array /* OUT */)
16262964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod{
163abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
16479420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod}
16579420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod
16605bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod
167706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod/*
168706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod * GSUB/GPOS
169706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod */
170706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
1717c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic const OT::GSUBGPOS&
17223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodget_gsubgpos_table (hb_face_t *face,
17323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod		    hb_tag_t   table_tag)
174706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1750ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  switch (table_tag) {
17623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GSUB: return _get_gsub (face);
17723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GPOS: return _get_gpos (face);
1787c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod    default:             return OT::Null(OT::GSUBGPOS);
179706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  }
180706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
181706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
182706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
183e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
184bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_script_tags (hb_face_t    *face,
185bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t      table_tag,
186e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				    unsigned int  start_offset,
187bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    unsigned int *script_count /* IN/OUT */,
188bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t     *script_tags /* OUT */)
189706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1907c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
191706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
192e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_script_tags (start_offset, script_count, script_tags);
193706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
194706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
195eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
196eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
197706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
1980ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_table_find_script (hb_face_t    *face,
1990ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      table_tag,
2000ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      script_tag,
2010ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				unsigned int *script_index)
202706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2037c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2047c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
205706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
206706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (g.find_script_index (script_tag, script_index))
2070594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
208706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
209706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try finding 'DFLT' */
2108a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
2110594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
212706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
213dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
214dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod   * including many versions of DejaVu Sans Mono! */
2158a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
2160594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
2172014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
218eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
219eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod     they're really trying to support Thai, for example :( */
220eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
221eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod    return false;
222eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
2232014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2240594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
2252014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod}
2262014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2272014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_bool_t
2282014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_ot_layout_table_choose_script (hb_face_t      *face,
2292014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  hb_tag_t        table_tag,
2302014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  const hb_tag_t *script_tags,
231c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  unsigned int   *script_index,
232c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  hb_tag_t       *chosen_script)
2332014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
2347c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2357c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2362014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2372014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  while (*script_tags)
2382014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  {
239c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (g.find_script_index (*script_tags, script_index)) {
240c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      if (chosen_script)
241c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod        *chosen_script = *script_tags;
2420594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
243c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    }
2442014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    script_tags++;
2452014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  }
2462014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2472014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try finding 'DFLT' */
248c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
249c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
250c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
2510594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
252c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
2532014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2542014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
255c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
256c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
257c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
2580594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
259c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
260706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
26171632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
26271632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod     they're really trying to support Thai, for example :( */
26371632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
26471632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod    if (chosen_script)
26571632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
2660594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
26771632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  }
26871632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod
269706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
270c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (chosen_script)
271c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2720594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
273706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
274706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
275e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
276bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
277bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
278e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
279bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
280bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
281c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
2827c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
283c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
284e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
285c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
286c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
287c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
288e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
289bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
290bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
291bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
292e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
293bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
294bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
295706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2967c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
297706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
298e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
299706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
300706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
301706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
3020ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
3030ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
3040ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
3050ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
3060ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
307706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
3087c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
3097c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
310706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3114a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
3120594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
313706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
314706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3158a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
3160594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
317706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3184a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3190594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
3204a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
321706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3224a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
3230ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
3240ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  hb_tag_t      table_tag,
3250ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  script_index,
3260ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  language_index,
3270ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int *feature_index)
3284a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
3297c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
330706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3314a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = l.get_required_feature_index ();
332706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3334a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
3344a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
335706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
336e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
337bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
338bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
339bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
340bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
341e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
342bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
343bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
3440ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3457c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3467c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3474a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
348e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
349c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
350c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
351e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
352bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
353bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
354bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
355bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
356e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
357bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
358bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
3590ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3607c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3617c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3624a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
363bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
364e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
365bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
3669897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
3679897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
3689897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
3699897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
3709897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
371bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
372bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
3734a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
3744a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3754a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3764a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
3770ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
3780ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
3790ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
3800ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
3810ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
3820ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
3834a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
3847c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
3857c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3867c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3874a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
388f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
389f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
3904a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
3914a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3924a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
3934a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
3940594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
3954a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
3964a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
397706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3984a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
3990594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
400706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
401c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
402e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
403f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodhb_ot_layout_feature_get_lookups (hb_face_t    *face,
404f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_tag_t      table_tag,
405f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  feature_index,
406f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  start_offset,
407f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_count /* IN/OUT */,
408f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_indexes /* OUT */)
409c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
4107c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4117c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Feature &f = g.get_feature (feature_index);
412c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
413e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
414c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
415c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
416a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
417a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
418a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_tag_t        table_tag,
419a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       unsigned int    feature_index,
420a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_set_t       *lookup_indexes /* OUT */)
421a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
422a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int lookup_indices[32];
423a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int offset, len;
424a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
425a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  offset = 0;
426a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  do {
427a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    len = ARRAY_LENGTH (lookup_indices);
428a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    hb_ot_layout_feature_get_lookups (face,
429a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      table_tag,
430a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      feature_index,
431a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      offset, &len,
432a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      lookup_indices);
433a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
434a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
435a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      lookup_indexes->add (lookup_indices[i]);
436a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
437a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    offset += len;
438a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } while (len == ARRAY_LENGTH (lookup_indices));
439a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
440a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
441a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
442a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
443a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_tag_t        table_tag,
444a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    script_index,
445a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    language_index,
446a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					const hb_tag_t *features,
447a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_set_t       *lookup_indexes /* OUT */)
448a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
449d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod  unsigned int required_feature_index;
450d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod  if (hb_ot_layout_language_get_required_feature_index (face,
451d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							table_tag,
452d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							script_index,
453d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							language_index,
454d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							&required_feature_index))
455733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    _hb_ot_layout_collect_lookups_lookups (face,
456733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   table_tag,
457733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   required_feature_index,
458733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   lookup_indexes);
459d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod
460a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!features)
461a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
462a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All features */
46315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int feature_indices[32];
46415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int offset, len;
46515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
46615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    offset = 0;
46715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    do {
46815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      len = ARRAY_LENGTH (feature_indices);
46915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      hb_ot_layout_language_get_feature_indexes (face,
47015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 table_tag,
47115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 script_index,
47215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 language_index,
47315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 offset, &len,
47415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 feature_indices);
47515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
47615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      for (unsigned int i = 0; i < len; i++)
47715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod	_hb_ot_layout_collect_lookups_lookups (face,
47815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       table_tag,
47915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       feature_indices[i],
48015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       lookup_indexes);
48115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
48215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      offset += len;
48315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    } while (len == ARRAY_LENGTH (feature_indices));
48415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
48515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
48615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
487a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *features; features++)
488a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
489a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int feature_index;
490733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_language_find_feature (face,
491733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
492733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
493733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
494733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      *features,
495733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      &feature_index))
496733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_lookups (face,
497733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
498733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       feature_index,
499733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
500a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
501a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
502a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
503a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
504a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
505a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
506a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_tag_t        table_tag,
507a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 unsigned int    script_index,
508a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *languages,
509a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *features,
510a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_set_t       *lookup_indexes /* OUT */)
511a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
512f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod  _hb_ot_layout_collect_lookups_features (face,
513f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  table_tag,
514f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  script_index,
515f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
516f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  features,
517f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  lookup_indexes);
518f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod
519a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!languages)
520a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
521a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All languages */
522733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_script_get_language_tags (face,
523733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								table_tag,
524733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								script_index,
525733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								0, NULL, NULL);
526a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int language_index = 0; language_index < count; language_index++)
527733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_features (face,
528733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
529733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
530733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
531733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      features,
532733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      lookup_indexes);
53315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
53415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
53515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
536a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *languages; languages++)
537a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
538a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int language_index;
539733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_script_find_language (face,
540733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     table_tag,
541733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     script_index,
542733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     *languages,
543733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     &language_index))
544733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_features (face,
545733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						table_tag,
546733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						script_index,
547733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						language_index,
548733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						features,
549733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						lookup_indexes);
550a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
551a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
552a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
553a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
554a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodvoid
555a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodhb_ot_layout_collect_lookups (hb_face_t      *face,
556a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_tag_t        table_tag,
557a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *scripts,
558a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *languages,
559a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *features,
560a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_set_t       *lookup_indexes /* OUT */)
561a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
562a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!scripts)
563a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
564a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All scripts */
565733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_table_get_script_tags (face,
566733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     table_tag,
567733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     0, NULL, NULL);
568a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int script_index = 0; script_index < count; script_index++)
569733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_languages (face,
570733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
571733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       script_index,
572733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       languages,
573733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       features,
574733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
57515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
57615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
57715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
578a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *scripts; scripts++)
579a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
580a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int script_index;
581733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_table_find_script (face,
582733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  table_tag,
583733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  *scripts,
584733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  &script_index))
585733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_languages (face,
586733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 table_tag,
587733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 script_index,
588733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 languages,
589733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 features,
590733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 lookup_indexes);
591a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
592a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
593a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
594a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
595e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodvoid
596e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodhb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
597e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_tag_t      table_tag,
598e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    unsigned int  lookup_index,
599e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
600e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
601e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
602e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
603e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod{
604e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
605e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
606733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod  OT::hb_collect_glyphs_context_t c (face,
607733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_before,
608733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_input,
609733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_after,
610733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_output);
611e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
61215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  switch (table_tag)
61315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
614e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GSUB:
615e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
616cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
617cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      l.collect_glyphs_lookup (&c);
618e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
619e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
620e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GPOS:
621e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
622cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
623cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      l.collect_glyphs_lookup (&c);
624e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
625e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
626e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  }
627e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod}
628e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
6292d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
6302d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
6317c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GSUB
6322d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
6332d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
6342d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
6350ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
6360ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
6377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gsub (face) != &OT::Null(OT::GSUB);
6380ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
6390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
640e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodhb_bool_t
641362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute (hb_face_t            *face,
642d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      unsigned int          lookup_index,
643e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const hb_codepoint_t *glyphs,
644e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      unsigned int          glyphs_length,
645d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      hb_bool_t             zero_context)
646e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
6476f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
648362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbod  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
649e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
650e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
651f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbodhb_bool_t
652362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
653d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   unsigned int          lookup_index,
654f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   const hb_codepoint_t *glyphs,
655f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   unsigned int          glyphs_length,
656d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   hb_bool_t             zero_context)
657f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod{
6586f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
6592bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
6602bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6612bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
6622bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
66345fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
664f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
665f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
66646d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
667afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
66846d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
6697c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_start (font, buffer);
67046d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
67146d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
67246d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
673afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
67446d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
6757c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_finish (font, buffer);
67646d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
67746d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
6785caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodvoid
679362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
680d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        unsigned int  lookup_index,
681d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        hb_set_t     *glyphs)
682f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod{
6839b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  OT::hb_closure_context_t c (face, glyphs);
6849b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
6859b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
6869b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
6879b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  l.closure (&c);
688f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod}
689bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
6909c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
6917c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GPOS
6929c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
6939c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
6949c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
6950ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
6960ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
6977c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gpos (face) != &OT::Null(OT::GPOS);
6980ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
6990ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
7008f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbodvoid
70105bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbodhb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
7028f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod{
7037c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GPOS::position_start (font, buffer);
7048f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod}
7058f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
7069db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
707568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbodhb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
7089db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
709568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  OT::GPOS::position_finish (font, buffer);
7109db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
711f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
712f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbodhb_bool_t
713875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbodhb_ot_layout_get_size_params (hb_face_t    *face,
714875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *design_size,       /* OUT.  May be NULL */
715875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
716875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
717875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_start,       /* OUT.  May be NULL */
718875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_end          /* OUT.  May be NULL */)
719f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod{
720f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  const OT::GPOS &gpos = _get_gpos (face);
721efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  const hb_tag_t tag = HB_TAG ('s','i','z','e');
722f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
7230dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  unsigned int num_features = gpos.get_feature_count ();
7240dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++)
7250dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  {
726efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod    if (tag == gpos.get_feature_tag (i))
727f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    {
7280dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod      const OT::Feature &f = gpos.get_feature (i);
729efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
730f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
731efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      if (params.designSize)
73285bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod      {
733efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod#define PARAM(a, A) if (a) *a = params.A
73485bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (design_size, designSize);
73585bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_id, subfamilyID);
73685bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_name_id, subfamilyNameID);
73785bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_start, rangeStart);
73885bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_end, rangeEnd);
73985bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod#undef PARAM
740efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod
741efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod	return true;
742efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      }
743f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    }
744f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  }
745f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
746875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#define PARAM(a, A) if (a) *a = 0
747efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (design_size, designSize);
748efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_id, subfamilyID);
749efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_name_id, subfamilyNameID);
750efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_start, rangeStart);
751efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_end, rangeEnd);
752875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#undef PARAM
753f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
754efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  return false;
755f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod}
756d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
757d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
758d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod/*
759bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod * Parts of different types are implemented here such that they have direct
760d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod * access to GSUB/GPOS lookups.
761d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod */
762d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
763d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
764bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GSUBProxy
765bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
766bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 0;
767bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::SubstLookup Lookup;
768bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
769bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy (hb_face_t *face) :
770bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gsub),
771bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
772bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
773bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GSUB &table;
774bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
775bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
776bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
777bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GPOSProxy
778bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
779bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 1;
780bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::PosLookup Lookup;
781bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
782bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy (hb_face_t *face) :
783bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gpos),
784bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
785bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
786bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GPOS &table;
787bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
788bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
789bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
790bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
791bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodtemplate <typename Proxy>
792bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodinline void hb_ot_map_t::apply (const Proxy &proxy,
793d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				const hb_ot_shape_plan_t *plan,
794d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_font_t *font,
795d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_buffer_t *buffer) const
796d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
797bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const unsigned int table_index = proxy.table_index;
798d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  unsigned int i = 0;
799bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  OT::hb_apply_context_t c (table_index, font, buffer);
800d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
801d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
802d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    const stage_map_t *stage = &stages[table_index][stage_index];
803d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    for (; i < stage->last_lookup; i++)
804bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    {
805bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      unsigned int lookup_index = lookups[table_index][i].index;
806bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_lookup_mask (lookups[table_index][i].mask);
807bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
808bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      proxy.table.get_lookup (lookup_index).apply_string (&c, &proxy.accels[lookup_index].digest);
809bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    }
810d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
811d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    if (stage->pause_func)
812d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    {
813d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      buffer->clear_output ();
814d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      stage->pause_func (plan, font, buffer);
815d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    }
816d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  }
817d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
818d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
819d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
820d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
821bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy proxy (font->face);
822bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
823d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
824d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
825d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
826d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
827bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy proxy (font->face);
828bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
829bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod}
830bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
831bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad EsfahbodHB_INTERNAL void
832bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodhb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
833bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const OT::SubstLookup &lookup,
834bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const hb_ot_layout_lookup_accelerator_t &accel)
835bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
836bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  lookup.apply_string (c, &accel.digest);
837d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
838