hb-ot-layout.cc revision 733e8c0d7bf0765884f2cc953c8edcd7ab7fb49b
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
37fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include <stdlib.h>
38aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod#include <string.h>
39aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
40acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
41cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
4211f4c87d01924cac43bf40044f67838440e19e42Behdad Esfahbod
430a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbodhb_ot_layout_t *
44266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_create (hb_face_t *face)
454a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
460a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
473dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod  if (unlikely (!layout))
483dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod    return NULL;
49555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod
507c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
517c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
5270e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
537c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
547c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
5570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
567c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
577c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
580a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod
596f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
606f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
616f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod
621336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
631336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
641336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
656f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) ||
666f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod		(layout->gpos_lookup_count && !layout->gpos_digests)))
671336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  {
681336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    _hb_ot_layout_destroy (layout);
691336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    return NULL;
701336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  }
711336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
726f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
733038ae6adbb61e55d6c665dea0c5271e0c9f0ed8Behdad Esfahbod    layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]);
746f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
753038ae6adbb61e55d6c665dea0c5271e0c9f0ed8Behdad Esfahbod    layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]);
761336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
770a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return layout;
78f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
79f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
8023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
81266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_destroy (hb_ot_layout_t *layout)
82fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
8370e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gdef_blob);
8470e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gsub_blob);
8570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gpos_blob);
86679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod
871336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  free (layout->gsub_digests);
881336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  free (layout->gpos_digests);
891336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
909ea7368fce3fa373d8d2925961ad211f5cf6ce70Behdad Esfahbod  free (layout);
9123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
92f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
937c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GDEF&
9423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
9523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
967c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
97ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gdef;
9823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
997c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GSUB&
10023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
101fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
1027c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
103ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gsub;
104fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
1057c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GPOS&
10623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
1072ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
1087c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
109ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gpos;
1102ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
1112ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
11223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
113590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
114590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
115590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
116590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
117590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
11852ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
119590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
12023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
121590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
122590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
1235a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_glyph_class_t
1245a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
1255a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod			      hb_codepoint_t  glyph)
1265a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod{
1275a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
1285a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod}
1294a2d844c2f12dc1b858ab4ddd737ded7c0852221Behdad Esfahbod
13089ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodvoid
13189ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodhb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
13289ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_ot_layout_glyph_class_t  klass,
13389ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_set_t                   *glyphs /* OUT */)
13489ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod{
13589ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
13689ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod}
13789ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod
138e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
1390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_attach_points (hb_face_t      *face,
14079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				hb_codepoint_t  glyph,
141e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int    start_offset,
14279420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_count /* IN/OUT */,
14379420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_array /* OUT */)
14479420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod{
145e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
14662964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod}
14762964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod
148e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
149e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbodhb_ot_layout_get_ligature_carets (hb_font_t      *font,
150e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_direction_t  direction,
151e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_codepoint_t  glyph,
152e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int    start_offset,
153e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int   *caret_count /* IN/OUT */,
154e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  int            *caret_array /* OUT */)
15562964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod{
156abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
15779420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod}
15879420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod
15905bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod
160706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod/*
161706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod * GSUB/GPOS
162706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod */
163706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
1647c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic const OT::GSUBGPOS&
16523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodget_gsubgpos_table (hb_face_t *face,
16623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod		    hb_tag_t   table_tag)
167706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  switch (table_tag) {
16923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GSUB: return _get_gsub (face);
17023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GPOS: return _get_gpos (face);
1717c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod    default:             return OT::Null(OT::GSUBGPOS);
172706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  }
173706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
174706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
175706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
176e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
177bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_script_tags (hb_face_t    *face,
178bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t      table_tag,
179e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				    unsigned int  start_offset,
180bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    unsigned int *script_count /* IN/OUT */,
181bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t     *script_tags /* OUT */)
182706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1837c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
184706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
185e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_script_tags (start_offset, script_count, script_tags);
186706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
187706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
188706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
1890ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_table_find_script (hb_face_t    *face,
1900ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      table_tag,
1910ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      script_tag,
1920ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				unsigned int *script_index)
193706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1947c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
1957c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
196706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
197706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (g.find_script_index (script_tag, script_index))
1980594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
199706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
200706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try finding 'DFLT' */
2018a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
2020594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
203706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
204dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
205dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod   * including many versions of DejaVu Sans Mono! */
2068a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
2070594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
2082014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2092014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2100594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
2112014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod}
2122014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2132014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_bool_t
2142014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_ot_layout_table_choose_script (hb_face_t      *face,
2152014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  hb_tag_t        table_tag,
2162014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  const hb_tag_t *script_tags,
217c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  unsigned int   *script_index,
218c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  hb_tag_t       *chosen_script)
2192014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
2207c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2217c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2222014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2232014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  while (*script_tags)
2242014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  {
225c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (g.find_script_index (*script_tags, script_index)) {
226c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      if (chosen_script)
227c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod        *chosen_script = *script_tags;
2280594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
229c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    }
2302014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    script_tags++;
2312014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  }
2322014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2332014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try finding 'DFLT' */
234c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
235c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
236c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
2370594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
238c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
2392014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2402014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
241c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
242c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
243c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
2440594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
245c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
246706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
24771632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
24871632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod     they're really trying to support Thai, for example :( */
24971632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
25071632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
25171632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod    if (chosen_script)
25271632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
2530594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
25471632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  }
25571632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod
256706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
257c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (chosen_script)
258c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2590594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
260706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
261706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
262e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
263bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
264bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
265e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
266bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
267bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
268c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
2697c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
270c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
271e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
272c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
273c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
274c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
275e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
276bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
277bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
278bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
279e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
280bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
281bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
282706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2837c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
284706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
285e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
286706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
287706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
288706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
2890ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
2900ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
2910ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
2920ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
2930ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
294706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2957c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
2967c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
297706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
2984a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
2990594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
300706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
301706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3028a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
3030594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
304706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3054a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3060594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
3074a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
308706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3094a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
3100ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
3110ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  hb_tag_t      table_tag,
3120ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  script_index,
3130ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  language_index,
3140ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int *feature_index)
3154a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
3167c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
317706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3184a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = l.get_required_feature_index ();
319706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3204a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
3214a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
322706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
323e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
324bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
325bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
326bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
327bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
328e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
329bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
330bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
3310ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3327c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3337c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3344a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
335e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
336c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
337c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
338e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
339bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
340bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
341bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
342bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
343e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
344bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
345bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
3460ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3477c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3487c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3494a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
350bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
351e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
352bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
3539897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
3549897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
3559897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
3569897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
3579897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
358bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
359bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
3604a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
3614a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3624a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3634a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
3640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
3650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
3660ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
3670ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
3680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
3690ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
3704a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
3717c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
3727c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3737c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3744a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
375f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
376f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
3774a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
3784a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3794a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
3804a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
3810594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
3824a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
3834a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
384706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3854a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
3860594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
387706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
388c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
389e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
390f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodhb_ot_layout_feature_get_lookups (hb_face_t    *face,
391f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_tag_t      table_tag,
392f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  feature_index,
393f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  start_offset,
394f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_count /* IN/OUT */,
395f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_indexes /* OUT */)
396c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
3977c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3987c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Feature &f = g.get_feature (feature_index);
399c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
400e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
401c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
402c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
403a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
404a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
405a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_tag_t        table_tag,
406a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       unsigned int    feature_index,
407a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_set_t       *lookup_indexes /* OUT */)
408a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
409a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int lookup_indices[32];
410a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int offset, len;
411a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
412a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  offset = 0;
413a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  do {
414a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    len = ARRAY_LENGTH (lookup_indices);
415a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    hb_ot_layout_feature_get_lookups (face,
416a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      table_tag,
417a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      feature_index,
418a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      offset, &len,
419a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      lookup_indices);
420a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
421a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
422a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      lookup_indexes->add (lookup_indices[i]);
423a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
424a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    offset += len;
425a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } while (len == ARRAY_LENGTH (lookup_indices));
426a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
427a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
428a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
429a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
430a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_tag_t        table_tag,
431a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    script_index,
432a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    language_index,
433a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					const hb_tag_t *features,
434a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_set_t       *lookup_indexes /* OUT */)
435a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
436d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod  unsigned int required_feature_index;
437d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod  if (hb_ot_layout_language_get_required_feature_index (face,
438d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							table_tag,
439d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							script_index,
440d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							language_index,
441d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod							&required_feature_index))
442733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    _hb_ot_layout_collect_lookups_lookups (face,
443733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   table_tag,
444733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   required_feature_index,
445733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					   lookup_indexes);
446d37ae38047bee12639741af9bb083b857fab950dBehdad Esfahbod
447a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!features)
448a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
449a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All features */
450733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_language_get_feature_tags (face,
451733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								 table_tag,
452733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								 script_index,
453733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								 language_index,
454733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								 0, NULL, NULL);
455a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int feature_index = 0; feature_index < count; feature_index++)
456733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_lookups (face,
457733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     table_tag,
458733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     feature_index,
459733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     lookup_indexes);
460a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } else {
461a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *features; features++)
462a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
463a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int feature_index;
464733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_language_find_feature (face,
465733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
466733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
467733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
468733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      *features,
469733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      &feature_index))
470733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_lookups (face,
471733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
472733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       feature_index,
473733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
474a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
475a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
476a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
477a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
478a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
479a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
480a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_tag_t        table_tag,
481a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 unsigned int    script_index,
482a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *languages,
483a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *features,
484a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_set_t       *lookup_indexes /* OUT */)
485a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
486a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!languages)
487a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
488a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All languages */
489733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_script_get_language_tags (face,
490733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								table_tag,
491733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								script_index,
492733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								0, NULL, NULL);
493a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int language_index = 0; language_index < count; language_index++)
494733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_features (face,
495733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
496733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
497733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
498733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      features,
499733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      lookup_indexes);
500a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } else {
501a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *languages; languages++)
502a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
503a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int language_index;
504733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_script_find_language (face,
505733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     table_tag,
506733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     script_index,
507733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     *languages,
508733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     &language_index))
509733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_features (face,
510733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						table_tag,
511733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						script_index,
512733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						language_index,
513733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						features,
514733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						lookup_indexes);
515a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
516a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
517a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
518a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
519a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodvoid
520a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodhb_ot_layout_collect_lookups (hb_face_t      *face,
521a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_tag_t        table_tag,
522a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *scripts,
523a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *languages,
524a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *features,
525a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_set_t       *lookup_indexes /* OUT */)
526a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
527a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!scripts)
528a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
529a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All scripts */
530733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_table_get_script_tags (face,
531733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     table_tag,
532733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     0, NULL, NULL);
533a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int script_index = 0; script_index < count; script_index++)
534733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_languages (face,
535733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
536733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       script_index,
537733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       languages,
538733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       features,
539733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
540a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } else {
541a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *scripts; scripts++)
542a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
543a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int script_index;
544733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_table_find_script (face,
545733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  table_tag,
546733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  *scripts,
547733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  &script_index))
548733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_languages (face,
549733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 table_tag,
550733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 script_index,
551733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 languages,
552733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 features,
553733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 lookup_indexes);
554a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
555a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
556a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
557a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
558e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodvoid
559e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodhb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
560e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_tag_t      table_tag,
561e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    unsigned int  lookup_index,
562e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
563e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
564e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
565e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
566e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod{
567e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
568e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
569733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod  OT::hb_collect_glyphs_context_t c (face,
570733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_before,
571733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_input,
572733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_after,
573733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_output);
574e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
575e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  switch (table_tag) {
576e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GSUB:
577e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
578cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
579cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      l.collect_glyphs_lookup (&c);
580e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
581e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
582e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GPOS:
583e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
584cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
585cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      l.collect_glyphs_lookup (&c);
586e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
587e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
588e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  }
589e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod}
590e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
5912d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5922d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
5937c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GSUB
5942d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
5952d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5962d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
5970ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
5980ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
5997c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gsub (face) != &OT::Null(OT::GSUB);
6000ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
6010ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
602e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodhb_bool_t
603362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute (hb_face_t            *face,
604d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      unsigned int          lookup_index,
605e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const hb_codepoint_t *glyphs,
606e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      unsigned int          glyphs_length,
607d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      hb_bool_t             zero_context)
608e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
6096f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
610362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbod  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
611e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
612e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
613f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbodhb_bool_t
614362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
615d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   unsigned int          lookup_index,
616f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   const hb_codepoint_t *glyphs,
617f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   unsigned int          glyphs_length,
618d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   hb_bool_t             zero_context)
619f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod{
6206f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
6212bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
6222bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6232bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
6242bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6252bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
626f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
627f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
62846d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
629afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
63046d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
6317c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_start (font, buffer);
63246d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
63346d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
6340ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
635afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_lookup (hb_font_t    *font,
636468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_buffer_t  *buffer,
637468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				unsigned int  lookup_index,
638468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_mask_t     mask)
6392d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod{
640afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false;
6412bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6422bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  OT::hb_apply_context_t c (font, buffer, mask);
6432bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6442bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
6452bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6462bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]);
647f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
648f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
64946d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
650afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
65146d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
6527c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_finish (font, buffer);
65346d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
65446d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
6555caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodvoid
656362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
657d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        unsigned int  lookup_index,
658d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        hb_set_t     *glyphs)
659f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod{
6609b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  OT::hb_closure_context_t c (face, glyphs);
6619b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
6629b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
6639b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
6649b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  l.closure (&c);
665f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod}
666bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
6679c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
6687c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GPOS
6699c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
6709c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
6719c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
6720ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
6730ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
6747c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gpos (face) != &OT::Null(OT::GPOS);
6750ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
6760ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
6778f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbodvoid
67805bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbodhb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
6798f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod{
6807c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GPOS::position_start (font, buffer);
6818f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod}
6828f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
6830ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
684f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbodhb_ot_layout_position_lookup (hb_font_t    *font,
685f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod			      hb_buffer_t  *buffer,
686f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod			      unsigned int  lookup_index,
687f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod			      hb_mask_t     mask)
6889c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod{
6896f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false;
6902bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6912bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  OT::hb_apply_context_t c (font, buffer, mask);
6922bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6932bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
6942bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
6952bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
696f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
697f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
6989db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
6991e7d860613032e40a3f90e2caa2ee5ac44ab8c8cBehdad Esfahbodhb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t zero_width_attached_marks)
7009db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
7017c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GPOS::position_finish (font, buffer, zero_width_attached_marks);
7029db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
703f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
704f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbodhb_bool_t
705875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbodhb_ot_layout_get_size_params (hb_face_t    *face,
706875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *design_size,       /* OUT.  May be NULL */
707875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
708875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
709875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_start,       /* OUT.  May be NULL */
710875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_end          /* OUT.  May be NULL */)
711f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod{
712f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  const OT::GPOS &gpos = _get_gpos (face);
713efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  const hb_tag_t tag = HB_TAG ('s','i','z','e');
714f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
7150dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  unsigned int num_features = gpos.get_feature_count ();
7160dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++)
7170dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  {
718efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod    if (tag == gpos.get_feature_tag (i))
719f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    {
7200dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod      const OT::Feature &f = gpos.get_feature (i);
721efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
722f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
723efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      if (params.designSize)
72485bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod      {
725efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod#define PARAM(a, A) if (a) *a = params.A
72685bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (design_size, designSize);
72785bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_id, subfamilyID);
72885bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_name_id, subfamilyNameID);
72985bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_start, rangeStart);
73085bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_end, rangeEnd);
73185bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod#undef PARAM
732efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod
733efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod	return true;
734efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      }
735f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    }
736f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  }
737f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
738875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#define PARAM(a, A) if (a) *a = 0
739efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (design_size, designSize);
740efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_id, subfamilyID);
741efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_name_id, subfamilyNameID);
742efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_start, rangeStart);
743efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_end, rangeEnd);
744875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#undef PARAM
745f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
746efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  return false;
747f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod}
748