hb-ot-layout.cc revision 395b35903e052aecc97d0807e4f813c64c0d2b0b
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.
545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod * Copyright © 2012,2013  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"
366c48f20eea22c6e686416ab4ec8388be3e8cd0b5Behdad Esfahbod#include "hb-ot-layout-jstf-table.hh"
37fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
38d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod#include "hb-ot-map-private.hh"
39d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
40fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include <stdlib.h>
41aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod#include <string.h>
42aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
44cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
4511f4c87d01924cac43bf40044f67838440e19e42Behdad Esfahbod
460a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbodhb_ot_layout_t *
47266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_create (hb_face_t *face)
484a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
490a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
503dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod  if (unlikely (!layout))
513dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod    return NULL;
52555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod
537c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
547c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
5570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
567c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
577c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
5870e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
597c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
607c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
610a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod
626f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
636f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
646f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod
6545fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
6645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
671336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
6845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
6945fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod		(layout->gpos_lookup_count && !layout->gpos_accels)))
701336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  {
711336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    _hb_ot_layout_destroy (layout);
721336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    return NULL;
731336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  }
741336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
756f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
7645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
776f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
7845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
791336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
800a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return layout;
81f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
82f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
8323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
84266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_destroy (hb_ot_layout_t *layout)
85fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
8645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
87395b35903e052aecc97d0807e4f813c64c0d2b0bBehdad Esfahbod    layout->gsub_accels[i].fini ();
8845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
89395b35903e052aecc97d0807e4f813c64c0d2b0bBehdad Esfahbod    layout->gpos_accels[i].fini ();
9045fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod
9145fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gsub_accels);
9245fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gpos_accels);
931336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
9489312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gdef_blob);
9589312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gsub_blob);
9689312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gpos_blob);
9789312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger
989ea7368fce3fa373d8d2925961ad211f5cf6ce70Behdad Esfahbod  free (layout);
9923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
100f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
1017c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GDEF&
10223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
10323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
1047c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
105ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gdef;
10623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
1077c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GSUB&
10823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
109fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
1107c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
111ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gsub;
112fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
1137c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GPOS&
11423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
1152ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
1167c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
117ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gpos;
1182ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
1192ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
12023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
121590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
122590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
123590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
124590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
125590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
12652ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
127590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
12823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
129590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
130590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
1315a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_glyph_class_t
1325a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
1335a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod			      hb_codepoint_t  glyph)
1345a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod{
1355a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
1365a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod}
1374a2d844c2f12dc1b858ab4ddd737ded7c0852221Behdad Esfahbod
13889ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodvoid
13989ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodhb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
14089ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_ot_layout_glyph_class_t  klass,
14189ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_set_t                   *glyphs /* OUT */)
14289ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod{
14389ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
14489ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod}
14589ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod
146e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
1470ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_attach_points (hb_face_t      *face,
14879420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				hb_codepoint_t  glyph,
149e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int    start_offset,
15079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_count /* IN/OUT */,
15179420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_array /* OUT */)
15279420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod{
153e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
15462964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod}
15562964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod
156e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
157e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbodhb_ot_layout_get_ligature_carets (hb_font_t      *font,
158e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_direction_t  direction,
159e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_codepoint_t  glyph,
160e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int    start_offset,
161e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int   *caret_count /* IN/OUT */,
162e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  int            *caret_array /* OUT */)
16362964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod{
164abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
16579420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod}
16679420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod
16705bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod
168706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod/*
169706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod * GSUB/GPOS
170706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod */
171706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
1727c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic const OT::GSUBGPOS&
17323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodget_gsubgpos_table (hb_face_t *face,
17423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod		    hb_tag_t   table_tag)
175706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1760ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  switch (table_tag) {
17723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GSUB: return _get_gsub (face);
17823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GPOS: return _get_gpos (face);
1797c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod    default:             return OT::Null(OT::GSUBGPOS);
180706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  }
181706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
182706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
183706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
184e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
185bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_script_tags (hb_face_t    *face,
186bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t      table_tag,
187e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				    unsigned int  start_offset,
188bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    unsigned int *script_count /* IN/OUT */,
189bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t     *script_tags /* OUT */)
190706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
1917c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
192706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
193e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_script_tags (start_offset, script_count, script_tags);
194706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
195706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
196eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
197eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
198706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
1990ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_table_find_script (hb_face_t    *face,
2000ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      table_tag,
2010ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      script_tag,
2020ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				unsigned int *script_index)
203706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2047c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2057c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
206706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
207706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (g.find_script_index (script_tag, script_index))
2080594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
209706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
210706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try finding 'DFLT' */
2118a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
2120594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
213706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
214dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
215dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod   * including many versions of DejaVu Sans Mono! */
2168a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
2170594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
2182014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
219eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
220eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod     they're really trying to support Thai, for example :( */
221eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
222eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod    return false;
223eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
2242014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2250594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
2262014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod}
2272014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2282014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_bool_t
2292014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_ot_layout_table_choose_script (hb_face_t      *face,
2302014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  hb_tag_t        table_tag,
2312014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  const hb_tag_t *script_tags,
232c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  unsigned int   *script_index,
233c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  hb_tag_t       *chosen_script)
2342014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
2357c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2367c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2372014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2382014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  while (*script_tags)
2392014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  {
240c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (g.find_script_index (*script_tags, script_index)) {
241c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      if (chosen_script)
242c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod        *chosen_script = *script_tags;
2430594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
244c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    }
2452014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    script_tags++;
2462014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  }
2472014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2482014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try finding 'DFLT' */
249c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
250c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
251c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
2520594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
253c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
2542014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2552014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
256c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
257c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
258c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
2590594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
260c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
261706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
26271632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
26371632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod     they're really trying to support Thai, for example :( */
26471632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
26571632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod    if (chosen_script)
26671632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
2670594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
26871632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  }
26971632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod
270706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
271c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (chosen_script)
272c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2730594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
274706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
275706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
276e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
277bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
278bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
279e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
280bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
281bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
282c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
2837c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
284c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
285e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
286c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
287c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
288c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
289e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
290bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
291bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
292bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
293e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
294bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
295bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
296706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2977c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
298706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
299e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
300706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
301706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
302706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
3030ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
3040ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
3050ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
3060ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
3070ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
308706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
3097c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
3107c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
311706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3124a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
3130594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
314706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
315706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3168a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
3170594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
318706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3194a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3200594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
3214a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
322706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3234a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
324911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
325911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  hb_tag_t      table_tag,
326911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int  script_index,
327911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int  language_index,
328911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int *feature_index)
329911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod{
330911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod  return hb_ot_layout_language_get_required_feature (face,
331911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     table_tag,
332911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     script_index,
333911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     language_index,
334911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     feature_index,
335911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     NULL);
336911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod}
337911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod
338911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbodhb_bool_t
339da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kewhb_ot_layout_language_get_required_feature (hb_face_t    *face,
340da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    hb_tag_t      table_tag,
341da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int  script_index,
342da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int  language_index,
343da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int *feature_index,
344da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    hb_tag_t     *feature_tag)
3454a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
346da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
347da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
348706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
349da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  unsigned int index = l.get_required_feature_index ();
350da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  if (feature_index) *feature_index = index;
351da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  if (feature_tag) *feature_tag = g.get_feature_tag (index);
352706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3534a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
3544a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
355706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
356e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
357bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
358bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
359bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
360bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
361e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
362bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
363bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
3640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3657c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3667c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3674a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
368e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
369c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
370c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
371e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
372bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
373bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
374bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
375bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
376e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
377bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
378bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
3790ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
3807c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3817c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3824a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
383bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
384e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
385bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
3869897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
3879897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
3889897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
3899897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
3909897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
391bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
392bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
3934a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
3944a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3954a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
3964a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
3970ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
3980ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
3990ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
4000ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
4010ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
4020ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
4034a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
4047c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
4057c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4067c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4074a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
408f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
409f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
4104a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
4114a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4124a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
4134a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
4140594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
4154a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
4164a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
417706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4184a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
4190594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
420706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
421c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
422e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
423f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodhb_ot_layout_feature_get_lookups (hb_face_t    *face,
424f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_tag_t      table_tag,
425f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  feature_index,
426f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  start_offset,
427f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_count /* IN/OUT */,
428f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_indexes /* OUT */)
429c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
4307c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4317c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Feature &f = g.get_feature (feature_index);
432c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
433e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
434c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
435c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
43627674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbodunsigned int
43727674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbodhb_ot_layout_table_get_lookup_count (hb_face_t    *face,
43827674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod				     hb_tag_t      table_tag)
43927674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod{
44027674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  switch (table_tag)
44127674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  {
44227674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    case HB_OT_TAG_GSUB:
44327674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    {
44427674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod      return hb_ot_layout_from_face (face)->gsub_lookup_count;
44527674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    }
44627674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    case HB_OT_TAG_GPOS:
44727674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    {
44827674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod      return hb_ot_layout_from_face (face)->gpos_lookup_count;
44927674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    }
45027674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  }
4514e6e53db5da0a5da87ae732c3f9d01babf4ae6c2Behdad Esfahbod  return 0;
45227674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod}
45327674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod
454a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
455a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
456a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_tag_t        table_tag,
457a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       unsigned int    feature_index,
458a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_set_t       *lookup_indexes /* OUT */)
459a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
460a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int lookup_indices[32];
461a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int offset, len;
462a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
463a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  offset = 0;
464a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  do {
465a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    len = ARRAY_LENGTH (lookup_indices);
466a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    hb_ot_layout_feature_get_lookups (face,
467a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      table_tag,
468a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      feature_index,
469a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      offset, &len,
470a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      lookup_indices);
471a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
472a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
473a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      lookup_indexes->add (lookup_indices[i]);
474a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
475a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    offset += len;
476a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } while (len == ARRAY_LENGTH (lookup_indices));
477a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
478a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
479a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
480a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
481a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_tag_t        table_tag,
482a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    script_index,
483a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    language_index,
484a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					const hb_tag_t *features,
485a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_set_t       *lookup_indexes /* OUT */)
486a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
487a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!features)
488a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
4895f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod    unsigned int required_feature_index;
490da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew    if (hb_ot_layout_language_get_required_feature (face,
491da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    table_tag,
492da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    script_index,
493da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    language_index,
494da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    &required_feature_index,
495da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    NULL))
4965f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod      _hb_ot_layout_collect_lookups_lookups (face,
4975f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     table_tag,
4985f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     required_feature_index,
4995f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     lookup_indexes);
5005f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod
501a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All features */
50215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int feature_indices[32];
50315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int offset, len;
50415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
50515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    offset = 0;
50615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    do {
50715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      len = ARRAY_LENGTH (feature_indices);
50815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      hb_ot_layout_language_get_feature_indexes (face,
50915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 table_tag,
51015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 script_index,
51115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 language_index,
51215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 offset, &len,
51315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 feature_indices);
51415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
51515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      for (unsigned int i = 0; i < len; i++)
51615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod	_hb_ot_layout_collect_lookups_lookups (face,
51715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       table_tag,
51815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       feature_indices[i],
51915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       lookup_indexes);
52015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
52115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      offset += len;
52215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    } while (len == ARRAY_LENGTH (feature_indices));
52315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
52415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
52515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
526a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *features; features++)
527a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
528a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int feature_index;
529733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_language_find_feature (face,
530733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
531733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
532733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
533733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      *features,
534733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      &feature_index))
535733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_lookups (face,
536733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
537733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       feature_index,
538733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
539a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
540a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
541a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
542a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
543a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
544a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
545a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_tag_t        table_tag,
546a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 unsigned int    script_index,
547a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *languages,
548a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *features,
549a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_set_t       *lookup_indexes /* OUT */)
550a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
551f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod  _hb_ot_layout_collect_lookups_features (face,
552f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  table_tag,
553f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  script_index,
554f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
555f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  features,
556f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  lookup_indexes);
557f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod
558a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!languages)
559a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
560a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All languages */
561733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_script_get_language_tags (face,
562733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								table_tag,
563733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								script_index,
564733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								0, NULL, NULL);
565a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int language_index = 0; language_index < count; language_index++)
566733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_features (face,
567733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
568733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
569733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
570733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      features,
571733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      lookup_indexes);
57215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
57315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
57415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
575a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *languages; languages++)
576a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
577a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int language_index;
578733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_script_find_language (face,
579733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     table_tag,
580733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     script_index,
581733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     *languages,
582733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     &language_index))
583733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_features (face,
584733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						table_tag,
585733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						script_index,
586733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						language_index,
587733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						features,
588733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						lookup_indexes);
589a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
590a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
591a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
592a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
593a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodvoid
594a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodhb_ot_layout_collect_lookups (hb_face_t      *face,
595a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_tag_t        table_tag,
596a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *scripts,
597a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *languages,
598a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *features,
599a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_set_t       *lookup_indexes /* OUT */)
600a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
601a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!scripts)
602a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
603a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All scripts */
604733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_table_get_script_tags (face,
605733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     table_tag,
606733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     0, NULL, NULL);
607a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int script_index = 0; script_index < count; script_index++)
608733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_languages (face,
609733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
610733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       script_index,
611733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       languages,
612733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       features,
613733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
61415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
61515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
61615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
617a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *scripts; scripts++)
618a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
619a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int script_index;
620733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_table_find_script (face,
621733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  table_tag,
622733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  *scripts,
623733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  &script_index))
624733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_languages (face,
625733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 table_tag,
626733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 script_index,
627733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 languages,
628733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 features,
629733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 lookup_indexes);
630a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
631a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
632a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
633a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
634e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodvoid
635e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodhb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
636e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_tag_t      table_tag,
637e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    unsigned int  lookup_index,
638e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
639e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
640e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
641e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
642e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod{
643e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
644e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
645733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod  OT::hb_collect_glyphs_context_t c (face,
646733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_before,
647733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_input,
648733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_after,
649733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_output);
650e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
65115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  switch (table_tag)
65215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
653e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GSUB:
654e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
655cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
656780cd930a974165d76dbf7a87701d11b7f15db06Behdad Esfahbod      l.collect_glyphs (&c);
657e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
658e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
659e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GPOS:
660e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
661cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
662780cd930a974165d76dbf7a87701d11b7f15db06Behdad Esfahbod      l.collect_glyphs (&c);
663e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
664e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
665e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  }
666e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod}
667e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
6682d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
6692d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
6707c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GSUB
6712d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
6722d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
6732d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
6740ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
6750ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
6767c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gsub (face) != &OT::Null(OT::GSUB);
6770ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
6780ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
679e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodhb_bool_t
680362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute (hb_face_t            *face,
681d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      unsigned int          lookup_index,
682e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const hb_codepoint_t *glyphs,
683e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      unsigned int          glyphs_length,
684d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      hb_bool_t             zero_context)
685e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
6866f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
687362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbod  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
688e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
689e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
690f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbodhb_bool_t
691362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
692d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   unsigned int          lookup_index,
693f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   const hb_codepoint_t *glyphs,
694f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   unsigned int          glyphs_length,
695d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   hb_bool_t             zero_context)
696f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod{
6976f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
6982bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
6992bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
7002bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
7012bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
70245fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index].digest);
703f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
704f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
70546d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
706afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
70746d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
7087c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_start (font, buffer);
70946d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
71046d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
71146d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
712afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
71346d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
7147c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_finish (font, buffer);
71546d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
71646d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
7175caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodvoid
718362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
719d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        unsigned int  lookup_index,
720d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        hb_set_t     *glyphs)
721f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod{
7229b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  OT::hb_closure_context_t c (face, glyphs);
7239b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
7249b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
7259b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
7269b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  l.closure (&c);
727f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod}
728bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
7299c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
7307c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GPOS
7319c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
7329c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
7339c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
7340ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
7350ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
7367c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gpos (face) != &OT::Null(OT::GPOS);
7370ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
7380ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
7398f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbodvoid
74005bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbodhb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
7418f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod{
7427c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GPOS::position_start (font, buffer);
7438f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod}
7448f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
7459db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
746568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbodhb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
7479db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
748568000274c8edb5f41bc4f876ce21fcc8bdaeed8Behdad Esfahbod  OT::GPOS::position_finish (font, buffer);
7499db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
750f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
751f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbodhb_bool_t
752875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbodhb_ot_layout_get_size_params (hb_face_t    *face,
753875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *design_size,       /* OUT.  May be NULL */
754875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
755875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
756875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_start,       /* OUT.  May be NULL */
757875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_end          /* OUT.  May be NULL */)
758f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod{
759f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  const OT::GPOS &gpos = _get_gpos (face);
760efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  const hb_tag_t tag = HB_TAG ('s','i','z','e');
761f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
7620dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  unsigned int num_features = gpos.get_feature_count ();
7630dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++)
7640dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  {
765efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod    if (tag == gpos.get_feature_tag (i))
766f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    {
7670dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod      const OT::Feature &f = gpos.get_feature (i);
768efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
769f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
770efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      if (params.designSize)
77185bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod      {
772efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod#define PARAM(a, A) if (a) *a = params.A
77385bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (design_size, designSize);
77485bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_id, subfamilyID);
77585bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_name_id, subfamilyNameID);
77685bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_start, rangeStart);
77785bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_end, rangeEnd);
77885bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod#undef PARAM
779efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod
780efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod	return true;
781efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      }
782f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    }
783f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  }
784f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
785875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#define PARAM(a, A) if (a) *a = 0
786efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (design_size, designSize);
787efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_id, subfamilyID);
788efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_name_id, subfamilyNameID);
789efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_start, rangeStart);
790efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_end, rangeEnd);
791875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#undef PARAM
792f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
793efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  return false;
794f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod}
795d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
796d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
797d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod/*
798bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod * Parts of different types are implemented here such that they have direct
799d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod * access to GSUB/GPOS lookups.
800d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod */
801d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
802d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
803bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GSUBProxy
804bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
805bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 0;
8066ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod  static const bool inplace = false;
807bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::SubstLookup Lookup;
808bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
809bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy (hb_face_t *face) :
810bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gsub),
811bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
812bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
813bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GSUB &table;
814bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
815bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
816bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
817bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GPOSProxy
818bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
819bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 1;
8206ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod  static const bool inplace = true;
821bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::PosLookup Lookup;
822bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
823bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy (hb_face_t *face) :
824bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gpos),
825bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
826bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
827bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GPOS &table;
828bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
829bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
830bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
831bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
83245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodtemplate <typename Lookup>
83345f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodstatic inline bool apply_once (OT::hb_apply_context_t *c,
83445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod			       const Lookup &lookup)
83545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod{
83645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  if (!c->check_glyph_property (&c->buffer->cur(), c->lookup_props))
83745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    return false;
83845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  return lookup.dispatch (c);
83945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod}
84045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
84145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodtemplate <typename Proxy>
84245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodstatic inline bool
84345f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodapply_string (OT::hb_apply_context_t *c,
84445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	      const typename Proxy::Lookup &lookup,
84545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	      const hb_ot_layout_lookup_accelerator_t &accel)
84645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod{
84745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  bool ret = false;
848ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
84945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
850ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  if (unlikely (!buffer->len || !c->lookup_mask))
85145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    return false;
85245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
85345f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  c->set_lookup (lookup);
85445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
85545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  if (likely (!lookup.is_reverse ()))
85645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  {
85745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    /* in/out forward substitution/positioning */
85845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    if (Proxy::table_index == 0)
859ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->clear_output ();
860ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    buffer->idx = 0;
86145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
862ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    while (buffer->idx < buffer->len)
86345f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    {
864ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      if (accel.digest.may_have (buffer->cur().codepoint) &&
865ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod	  (buffer->cur().mask & c->lookup_mask) &&
86645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	  apply_once (c, lookup))
86745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	ret = true;
86845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod      else
869ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod	buffer->next_glyph ();
87045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    }
8719d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod    if (ret)
8729d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod    {
8736ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod      if (!Proxy::inplace)
874ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod	buffer->swap_buffers ();
8759d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod      else
876ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod        assert (!buffer->has_separate_output ());
8779d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod    }
87845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  }
87945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  else
88045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  {
88145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    /* in-place backward substitution/positioning */
88245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    if (Proxy::table_index == 0)
883ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->remove_output ();
884ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    buffer->idx = buffer->len - 1;
88545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    do
88645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    {
887ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      if (accel.digest.may_have (buffer->cur().codepoint) &&
888ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod	  (buffer->cur().mask & c->lookup_mask) &&
88945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	  apply_once (c, lookup))
89045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	ret = true;
89149901862e36e1c153835877a9f1183729333bbbeBehdad Esfahbod      /* The reverse lookup doesn't "advance" cursor (for good reason). */
892ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->idx--;
89345f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
89445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    }
895ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    while ((int) buffer->idx >= 0);
89645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  }
89745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
89845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  return ret;
89945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod}
90045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
901bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodtemplate <typename Proxy>
902bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodinline void hb_ot_map_t::apply (const Proxy &proxy,
903d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				const hb_ot_shape_plan_t *plan,
904d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_font_t *font,
905d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_buffer_t *buffer) const
906d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
907bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const unsigned int table_index = proxy.table_index;
908d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  unsigned int i = 0;
909bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  OT::hb_apply_context_t c (table_index, font, buffer);
91045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
911d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
912d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
913d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    const stage_map_t *stage = &stages[table_index][stage_index];
914d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    for (; i < stage->last_lookup; i++)
915bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    {
916bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      unsigned int lookup_index = lookups[table_index][i].index;
917bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_lookup_mask (lookups[table_index][i].mask);
918bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
91945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod      apply_string<Proxy> (&c,
92045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod			   proxy.table.get_lookup (lookup_index),
92145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod			   proxy.accels[lookup_index]);
922bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    }
923d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
924d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    if (stage->pause_func)
925d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    {
926d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      buffer->clear_output ();
927d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      stage->pause_func (plan, font, buffer);
928d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    }
929d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  }
930d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
931d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
932d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
933d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
934bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy proxy (font->face);
935bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
936d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
937d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
938d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
939d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
940bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy proxy (font->face);
941bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
942bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod}
943bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
944bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad EsfahbodHB_INTERNAL void
945bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodhb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
946bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const OT::SubstLookup &lookup,
947bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const hb_ot_layout_lookup_accelerator_t &accel)
948bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
94945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  apply_string<GSUBProxy> (c, lookup, accel);
950d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
951