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
3177a1a2bc18e7b04d4e352a8777ccce345b2f8659Behdad Esfahbod#include "hb-open-type-private.hh"
3222da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-ot-layout-private.hh"
33fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
347a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gdef-table.hh"
357a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gsub-table.hh"
367a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gpos-table.hh"
376c48f20eea22c6e686416ab4ec8388be3e8cd0b5Behdad Esfahbod#include "hb-ot-layout-jstf-table.hh"
38fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
39d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod#include "hb-ot-map-private.hh"
40d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
41fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include <stdlib.h>
42aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod#include <string.h>
43aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
44acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
45cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
4611f4c87d01924cac43bf40044f67838440e19e42Behdad Esfahbod
470a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbodhb_ot_layout_t *
48266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_create (hb_face_t *face)
494a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
500a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
513dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod  if (unlikely (!layout))
523dcbdc2125c04c173f29f04922fc031929893f4eBehdad Esfahbod    return NULL;
53555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod
547c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
557c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
5670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
577c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
587c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
5970e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
607c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
617c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
620a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod
63e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod  {
64e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    /*
65e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod     * The ugly business of blacklisting individual fonts' tables happen here!
66e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod     * See this thread for why we finally had to bend in and do this:
67e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
68e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod     */
69e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob);
70e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob);
71e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob);
72e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    if (0
73e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) /* Windows 7 timesi.ttf */
74e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) /* Windows 7 timesbi.ttf */
754f3d59a1877dcb94d09da48e9694a6c1b05a86feBehdad Esfahbod      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) /* Windows ??? timesi.ttf */
764f3d59a1877dcb94d09da48e9694a6c1b05a86feBehdad Esfahbod      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) /* Windows ??? timesbi.ttf */
7794dd0bb7e78125994cb7c833a5b03110f1ffc822Behdad Esfahbod      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Italic.ttf */
7894dd0bb7e78125994cb7c833a5b03110f1ffc822Behdad Esfahbod      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) /* OS X 10.11.3 Times New Roman Bold Italic.ttf */
79e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    )
80e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    {
81e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod      /* In certain versions of Times New Roman Italic and Bold Italic,
82e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
83e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
84e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       * double-quote.  See:
85e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
86e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       */
87e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod     if (3 == layout->gdef->get_glyph_class (5))
88e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod       layout->gdef = &OT::Null(OT::GDEF);
89e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod    }
90e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod  }
91e23cf902e91142a10229e3514be4ceee69efde04Behdad Esfahbod
926f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
936f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
946f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod
9545fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
9645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
971336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
9845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
9945fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod		(layout->gpos_lookup_count && !layout->gpos_accels)))
1001336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  {
1011336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    _hb_ot_layout_destroy (layout);
1021336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod    return NULL;
1031336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod  }
1041336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
1056f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
10645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
1076f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
10845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
1091336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
1100a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return layout;
111f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
112f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
11323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
114266b34418c9bbe23ccaf29cb354b58c465fa3b22Behdad Esfahbod_hb_ot_layout_destroy (hb_ot_layout_t *layout)
115fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
11645fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
117395b35903e052aecc97d0807e4f813c64c0d2b0bBehdad Esfahbod    layout->gsub_accels[i].fini ();
11845fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
119395b35903e052aecc97d0807e4f813c64c0d2b0bBehdad Esfahbod    layout->gpos_accels[i].fini ();
12045fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod
12145fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gsub_accels);
12245fd9424c723f115ca98995b8f8a25185a6fc71dBehdad Esfahbod  free (layout->gpos_accels);
1231336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod
12489312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gdef_blob);
12589312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gsub_blob);
12689312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger  hb_blob_destroy (layout->gpos_blob);
12789312b7417c0198a0635ca6b7e8ea11f6af2a4f8Bradley Grainger
1289ea7368fce3fa373d8d2925961ad211f5cf6ce70Behdad Esfahbod  free (layout);
12923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
130f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
1317c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GDEF&
13223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
13323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
1347c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
135ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gdef;
13623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
1377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GSUB&
13823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
139fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
1407c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
141ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gsub;
142fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
1437c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic inline const OT::GPOS&
14423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
1452ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
1467c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
147ea278d3895fe0c92801d692cd71d8d9f1de7c048Behdad Esfahbod  return *hb_ot_layout_from_face (face)->gpos;
1482ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
1492ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
15023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
151590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
152590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
153590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
154590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
155590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
15652ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
157590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
15823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
159590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
160590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
16101c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
16235d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod * hb_ot_layout_get_glyph_class:
16335d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod *
16401c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
16501c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
1665a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_glyph_class_t
1675a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
1685a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod			      hb_codepoint_t  glyph)
1695a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod{
1705a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
1715a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod}
1724a2d844c2f12dc1b858ab4ddd737ded7c0852221Behdad Esfahbod
17301c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
17435d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod * hb_ot_layout_get_glyphs_in_class:
17535d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod *
17601c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
17701c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
17889ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodvoid
17989ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbodhb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
18089ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_ot_layout_glyph_class_t  klass,
18189ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod				  hb_set_t                   *glyphs /* OUT */)
18289ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod{
18389ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
18489ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod}
18589ca8eeb83fedde06727d386369a0a39d410f12bBehdad Esfahbod
186e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
1870ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_attach_points (hb_face_t      *face,
18879420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				hb_codepoint_t  glyph,
189e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int    start_offset,
19079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_count /* IN/OUT */,
19179420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_array /* OUT */)
19279420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod{
193e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
19462964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod}
19562964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod
196e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
197e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbodhb_ot_layout_get_ligature_carets (hb_font_t      *font,
198e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_direction_t  direction,
199e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  hb_codepoint_t  glyph,
200e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int    start_offset,
201e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  unsigned int   *caret_count /* IN/OUT */,
202e204674fe340a57c48a9fe7e1ed02a9a08f4aca4Behdad Esfahbod				  int            *caret_array /* OUT */)
20362964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod{
204abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
20579420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod}
20679420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod
20705bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod
208706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod/*
209706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod * GSUB/GPOS
210706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod */
211706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
2127c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodstatic const OT::GSUBGPOS&
21323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodget_gsubgpos_table (hb_face_t *face,
21423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod		    hb_tag_t   table_tag)
215706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2160ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  switch (table_tag) {
21723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GSUB: return _get_gsub (face);
21823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GPOS: return _get_gpos (face);
2197c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod    default:             return OT::Null(OT::GSUBGPOS);
220706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  }
221706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
222706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
223706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
224e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
225bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_script_tags (hb_face_t    *face,
226bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t      table_tag,
227e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				    unsigned int  start_offset,
228bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    unsigned int *script_count /* IN/OUT */,
229bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t     *script_tags /* OUT */)
230706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2317c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
232706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
233e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_script_tags (start_offset, script_count, script_tags);
234706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
235706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
236eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
237eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
238706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
2390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_table_find_script (hb_face_t    *face,
2400ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      table_tag,
2410ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      script_tag,
2420ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				unsigned int *script_index)
243706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
2447c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2457c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
246706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
247706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (g.find_script_index (script_tag, script_index))
2480594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
249706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
250706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try finding 'DFLT' */
2518a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
2520594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
253706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
254dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
255dca8aff24652c83c53efbb9d06e5e1c7ef1c2fa5Behdad Esfahbod   * including many versions of DejaVu Sans Mono! */
2568a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
2570594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
2582014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
259eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
260eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod     they're really trying to support Thai, for example :( */
261eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
262eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod    return false;
263eb45c0a2fbaeeb34e77a2935934e8d1302728ec8Behdad Esfahbod
2642014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2650594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
2662014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod}
2672014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2682014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_bool_t
2692014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_ot_layout_table_choose_script (hb_face_t      *face,
2702014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  hb_tag_t        table_tag,
2712014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  const hb_tag_t *script_tags,
272c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  unsigned int   *script_index,
273c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod				  hb_tag_t       *chosen_script)
2742014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
2757c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2767c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2772014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2782014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  while (*script_tags)
2792014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  {
280c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (g.find_script_index (*script_tags, script_index)) {
281c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      if (chosen_script)
282c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod        *chosen_script = *script_tags;
2830594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
284c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    }
2852014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    script_tags++;
2862014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  }
2872014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2882014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try finding 'DFLT' */
289c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
290c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
291c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
2920594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
293c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
2942014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
2952014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
296c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
297c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    if (chosen_script)
298c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
2990594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
300c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  }
301706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
30271632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  /* try with 'latn'; some old fonts put their features there even though
30371632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod     they're really trying to support Thai, for example :( */
30471632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
30571632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod    if (chosen_script)
30671632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
3070594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
30871632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod  }
30971632c96daa4ba15e13f4d9e7f2c121d0162614eBehdad Esfahbod
310706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
311c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod  if (chosen_script)
312c47a31fb4793b825f4be57e9cb1b10db352b9512Behdad Esfahbod    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
3130594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
314706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
315706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
316e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
317bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
318bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
319e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
320bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
321bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
322c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
3237c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
324c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
325e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
326c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
327c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
3280f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbodhb_bool_t
3290f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbodhb_ot_layout_table_find_feature (hb_face_t    *face,
3300f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod				 hb_tag_t      table_tag,
3310f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod				 hb_tag_t      feature_tag,
3320f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod				 unsigned int *feature_index)
3330f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod{
3340f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
3350f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3360f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod
3370f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  unsigned int num_features = g.get_feature_count ();
3380f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  for (unsigned int i = 0; i < num_features; i++)
3390f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  {
3400f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod    if (feature_tag == g.get_feature_tag (i)) {
3410f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod      if (feature_index) *feature_index = i;
3420f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod      return true;
3430f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod    }
3440f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  }
3450f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod
3460f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
3470f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod  return false;
3480f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod}
3490f98fe88f42471eb8fb28d08d45eca9cd8303f7aBehdad Esfahbod
350c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
351e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
352bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
353bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
354bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
355e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
356bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
357bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
358706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
3597c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
360706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
361e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
362706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
363706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
364706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
3650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
3660ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
3670ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
3680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
3690ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
370706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
3717c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
3727c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
373706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3744a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
3750594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
376706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
377706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3788a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
3790594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
380706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3814a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3820594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
3834a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
384706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
3854a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
386911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
387911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  hb_tag_t      table_tag,
388911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int  script_index,
389911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int  language_index,
390911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						  unsigned int *feature_index)
391911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod{
392911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod  return hb_ot_layout_language_get_required_feature (face,
393911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     table_tag,
394911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     script_index,
395911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     language_index,
396911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     feature_index,
397911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod						     NULL);
398911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod}
399911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbod
40001c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
40135d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod * hb_ot_layout_language_get_required_feature:
40235d18585fc57750d817f57bfffe569069f9803b5Behdad Esfahbod *
40301c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.30
40401c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
405911ca38645bd51764e7859bc482319e8f6d2f710Behdad Esfahbodhb_bool_t
406da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kewhb_ot_layout_language_get_required_feature (hb_face_t    *face,
407da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    hb_tag_t      table_tag,
408da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int  script_index,
409da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int  language_index,
410da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    unsigned int *feature_index,
411da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew					    hb_tag_t     *feature_tag)
4124a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
413da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
414da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
415706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
416da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  unsigned int index = l.get_required_feature_index ();
417da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  if (feature_index) *feature_index = index;
418da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  if (feature_tag) *feature_tag = g.get_feature_tag (index);
419706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4204a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
4214a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
422706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
423e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
424bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
425bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
426bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
427bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
428e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
429bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
430bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
4310ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
4327c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4337c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4344a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
435e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
436c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
437c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
438e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
439bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
440bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
441bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
442bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
443e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
444bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
445bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
4460ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
4477c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4487c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4494a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
450bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
451e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
452bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
4539897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
4549897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
4559897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
4569897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
4579897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
458bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
459bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
4604a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
4614a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4624a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4634a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
4640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
4650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
4660ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
4670ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
4680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
4690ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
4704a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
4717c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
4727c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4737c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4744a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
475f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
476f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
4774a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
4784a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4794a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
4804a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
4810594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      return true;
4824a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
4834a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
484706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4854a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
4860594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return false;
487706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
488c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
48901c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
490d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_feature_get_lookups:
491d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
49201c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
49301c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
494e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
495f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbodhb_ot_layout_feature_get_lookups (hb_face_t    *face,
496f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  hb_tag_t      table_tag,
497f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  feature_index,
498f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int  start_offset,
499f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_count /* IN/OUT */,
500f30641038ba96e83950729b1bd9d86d2e98e46c5Behdad Esfahbod				  unsigned int *lookup_indexes /* OUT */)
501c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
5027c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
5037c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::Feature &f = g.get_feature (feature_index);
504c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
505e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
506c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
507c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
50801c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
509d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_table_get_lookup_count:
510d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
51101c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.22
51201c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
51327674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbodunsigned int
51427674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbodhb_ot_layout_table_get_lookup_count (hb_face_t    *face,
51527674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod				     hb_tag_t      table_tag)
51627674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod{
51727674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  switch (table_tag)
51827674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  {
51927674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    case HB_OT_TAG_GSUB:
52027674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    {
52127674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod      return hb_ot_layout_from_face (face)->gsub_lookup_count;
52227674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    }
52327674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    case HB_OT_TAG_GPOS:
52427674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    {
52527674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod      return hb_ot_layout_from_face (face)->gpos_lookup_count;
52627674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod    }
52727674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod  }
5284e6e53db5da0a5da87ae732c3f9d01babf4ae6c2Behdad Esfahbod  return 0;
52927674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod}
53027674b4bb351e501373bd9994e4ba6546e465cf7Behdad Esfahbod
531a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
532a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
533a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_tag_t        table_tag,
534a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       unsigned int    feature_index,
535a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				       hb_set_t       *lookup_indexes /* OUT */)
536a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
537a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int lookup_indices[32];
538a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  unsigned int offset, len;
539a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
540a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  offset = 0;
541a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  do {
542a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    len = ARRAY_LENGTH (lookup_indices);
543a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    hb_ot_layout_feature_get_lookups (face,
544a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      table_tag,
545a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      feature_index,
546a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      offset, &len,
547a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod				      lookup_indices);
548a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
549a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int i = 0; i < len; i++)
550a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      lookup_indexes->add (lookup_indices[i]);
551a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
552a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    offset += len;
553a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  } while (len == ARRAY_LENGTH (lookup_indices));
554a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
555a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
556a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
557a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
558a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_tag_t        table_tag,
559a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    script_index,
560a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					unsigned int    language_index,
561a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					const hb_tag_t *features,
562a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					hb_set_t       *lookup_indexes /* OUT */)
563a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
564a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!features)
565a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
5665f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod    unsigned int required_feature_index;
567da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew    if (hb_ot_layout_language_get_required_feature (face,
568da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    table_tag,
569da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    script_index,
570da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    language_index,
571da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    &required_feature_index,
572da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew						    NULL))
5735f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod      _hb_ot_layout_collect_lookups_lookups (face,
5745f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     table_tag,
5755f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     required_feature_index,
5765f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod					     lookup_indexes);
5775f85c80a07dd2d18348824866bf4e984ac711a24Behdad Esfahbod
578a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All features */
57915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int feature_indices[32];
58015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    unsigned int offset, len;
58115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
58215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    offset = 0;
58315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    do {
58415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      len = ARRAY_LENGTH (feature_indices);
58515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      hb_ot_layout_language_get_feature_indexes (face,
58615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 table_tag,
58715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 script_index,
58815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 language_index,
58915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 offset, &len,
59015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod						 feature_indices);
59115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
59215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      for (unsigned int i = 0; i < len; i++)
59315e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod	_hb_ot_layout_collect_lookups_lookups (face,
59415e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       table_tag,
59515e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       feature_indices[i],
59615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod					       lookup_indexes);
59715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod
59815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod      offset += len;
59915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod    } while (len == ARRAY_LENGTH (feature_indices));
60015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
60115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
60215e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
603a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *features; features++)
604a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
605a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int feature_index;
606733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_language_find_feature (face,
607733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
608733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
609733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
610733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      *features,
611733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      &feature_index))
612733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_lookups (face,
613733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
614733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       feature_index,
615733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
616a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
617a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
618a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
619a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
620a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodstatic void
621a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
622a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_tag_t        table_tag,
623a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 unsigned int    script_index,
624a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *languages,
625a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 const hb_tag_t *features,
626a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod					 hb_set_t       *lookup_indexes /* OUT */)
627a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
628f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod  _hb_ot_layout_collect_lookups_features (face,
629f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  table_tag,
630f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  script_index,
631f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
632f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  features,
633f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod					  lookup_indexes);
634f0c82410dbe800cb6429ba4aa7cfd9f5a11cc70cBehdad Esfahbod
635a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!languages)
636a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
637a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All languages */
638733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_script_get_language_tags (face,
639733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								table_tag,
640733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								script_index,
641733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod								0, NULL, NULL);
642a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int language_index = 0; language_index < count; language_index++)
643733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_features (face,
644733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      table_tag,
645733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      script_index,
646733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      language_index,
647733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      features,
648733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					      lookup_indexes);
64915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
65015e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
65115e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
652a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *languages; languages++)
653a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
654a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int language_index;
655733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_script_find_language (face,
656733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     table_tag,
657733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     script_index,
658733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     *languages,
659733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					     &language_index))
660733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_features (face,
661733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						table_tag,
662733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						script_index,
663733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						language_index,
664733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						features,
665733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						lookup_indexes);
666a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
667a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
668a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
669a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
67001c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
671d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_collect_lookups:
672d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
67301c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.8
67401c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
675a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodvoid
676a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbodhb_ot_layout_collect_lookups (hb_face_t      *face,
677a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_tag_t        table_tag,
678a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *scripts,
679a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *languages,
680a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      const hb_tag_t *features,
681a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod			      hb_set_t       *lookup_indexes /* OUT */)
682a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod{
683a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  if (!scripts)
684a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  {
685a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    /* All scripts */
686733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod    unsigned int count = hb_ot_layout_table_get_script_tags (face,
687733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     table_tag,
688733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod							     0, NULL, NULL);
689a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (unsigned int script_index = 0; script_index < count; script_index++)
690733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      _hb_ot_layout_collect_lookups_languages (face,
691733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       table_tag,
692733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       script_index,
693733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       languages,
694733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       features,
695733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					       lookup_indexes);
69615e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  }
69715e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  else
69815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
699a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    for (; *scripts; scripts++)
700a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    {
701a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod      unsigned int script_index;
702733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod      if (hb_ot_layout_table_find_script (face,
703733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  table_tag,
704733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  *scripts,
705733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod					  &script_index))
706733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod        _hb_ot_layout_collect_lookups_languages (face,
707733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 table_tag,
708733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 script_index,
709733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 languages,
710733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 features,
711733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod						 lookup_indexes);
712a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod    }
713a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod  }
714a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod}
715a88e7160217b9f44e4e5b4b814d0ca98c457ee40Behdad Esfahbod
71601c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
717d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_lookup_collect_glyphs:
718d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
71901c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
72001c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
721e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodvoid
722e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodhb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
723e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_tag_t      table_tag,
724e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    unsigned int  lookup_index,
725e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
726e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
727e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
728e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
729e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod{
730e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
731e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
732733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod  OT::hb_collect_glyphs_context_t c (face,
733733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_before,
734733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_input,
735733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_after,
736733e8c0d7bf0765884f2cc953c8edcd7ab7fb49bBehdad Esfahbod				     glyphs_output);
737e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
73815e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  switch (table_tag)
73915e9e4e1ddaad655988144e7a56a765e8adf8782Behdad Esfahbod  {
740e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GSUB:
741e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
742cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
743780cd930a974165d76dbf7a87701d11b7f15db06Behdad Esfahbod      l.collect_glyphs (&c);
744e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
745e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
746e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    case HB_OT_TAG_GPOS:
747e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    {
748cdd756b9f40665a201f5c4e65a87b9a27c390601Behdad Esfahbod      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
749780cd930a974165d76dbf7a87701d11b7f15db06Behdad Esfahbod      l.collect_glyphs (&c);
750e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod      return;
751e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    }
752e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  }
753e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod}
754e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
7552d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
7562d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
7577c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GSUB
7582d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
7592d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
7602d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
7610ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
7620ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
7637c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gsub (face) != &OT::Null(OT::GSUB);
7640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
7650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
76601c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
767d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_lookup_would_substitute:
768d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
76901c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
77001c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
771e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodhb_bool_t
772362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute (hb_face_t            *face,
773d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      unsigned int          lookup_index,
774e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const hb_codepoint_t *glyphs,
775e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      unsigned int          glyphs_length,
776d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				      hb_bool_t             zero_context)
777e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
7786f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
779362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbod  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
780e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
781e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
782f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbodhb_bool_t
783362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
784d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   unsigned int          lookup_index,
785f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   const hb_codepoint_t *glyphs,
786f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod					   unsigned int          glyphs_length,
787d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod					   hb_bool_t             zero_context)
788f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod{
7896f7611375521c6d285a9aa763f2ea5cb44cd0d39Behdad Esfahbod  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
790ea512f71084296be3bd893f78650def894066de0Behdad Esfahbod  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
7912bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
7922bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
7932bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod
794241eac9559465fa79f396570af4e87f455b7e9d5Behdad Esfahbod  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
795f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod}
796f860366456d9e59b139a940da6d89c3c4fb9e96eBehdad Esfahbod
79746d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbodvoid
798afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbodhb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
79946d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod{
8007c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GSUB::substitute_start (font, buffer);
80146d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod}
80246d6a21cc8613519e6ce27b1925e29285cccb71dBehdad Esfahbod
80301c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
804d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_lookup_substitute_closure:
805d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
80601c3a88543850c87483fd8671044df53b368c520Sascha Brawer * Since: 0.9.7
80701c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
8085caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodvoid
809362a990b2246f5448ecb9d600761f710aea7d42dBehdad Esfahbodhb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
810d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        unsigned int  lookup_index,
811d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod				        hb_set_t     *glyphs)
812f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod{
8139b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  OT::hb_closure_context_t c (face, glyphs);
8149b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
8159b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
8169b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
8179b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  l.closure (&c);
818f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod}
819bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
8209c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
8217c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod * OT::GPOS
8229c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
8239c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
8249c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
8250ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
8260ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
8277c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  return &_get_gpos (face) != &OT::Null(OT::GPOS);
8280ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
8290ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
8308f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbodvoid
83105bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbodhb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
8328f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod{
8337c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  OT::GPOS::position_start (font, buffer);
8348f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod}
8358f0d7e0c3fd4b05c43ac449be4f374dc2dc56127Behdad Esfahbod
8369db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
8377d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbodhb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
8387d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbod{
8397d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbod  OT::GPOS::position_finish_advances (font, buffer);
8407d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbod}
8417d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbod
8427d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbodvoid
8437d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbodhb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
8449db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
8457d8d58ac81fe267e29ea68cdc6f4a4fa8c22d40fBehdad Esfahbod  OT::GPOS::position_finish_offsets (font, buffer);
8469db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
847f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
84801c3a88543850c87483fd8671044df53b368c520Sascha Brawer/**
849d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny * hb_ot_layout_get_size_params:
850d7bf9d05c519a369a7b3a02e9ed5ecc05a20cd3eKhaled Hosny *
851b8811429b6810c4f13be087b593a862c17d9d987Behdad Esfahbod * Since: 0.9.10
85201c3a88543850c87483fd8671044df53b368c520Sascha Brawer **/
853f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbodhb_bool_t
854875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbodhb_ot_layout_get_size_params (hb_face_t    *face,
855875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *design_size,       /* OUT.  May be NULL */
856875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
857875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
858875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_start,       /* OUT.  May be NULL */
859875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod			      unsigned int *range_end          /* OUT.  May be NULL */)
860f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod{
861f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  const OT::GPOS &gpos = _get_gpos (face);
862efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  const hb_tag_t tag = HB_TAG ('s','i','z','e');
863f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
8640dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  unsigned int num_features = gpos.get_feature_count ();
8650dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++)
8660dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod  {
867efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod    if (tag == gpos.get_feature_tag (i))
868f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    {
8690dff11f6bfbda444a153ca75ff2b947f94e9b3c5Behdad Esfahbod      const OT::Feature &f = gpos.get_feature (i);
870efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
871f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
872efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      if (params.designSize)
87385bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod      {
874efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod#define PARAM(a, A) if (a) *a = params.A
87585bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (design_size, designSize);
87685bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_id, subfamilyID);
87785bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (subfamily_name_id, subfamilyNameID);
87885bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_start, rangeStart);
87985bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod	PARAM (range_end, rangeEnd);
88085bc44b90a19c6a669ed567a9cd8513448600afeBehdad Esfahbod#undef PARAM
881efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod
882efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod	return true;
883efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod      }
884f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod    }
885f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod  }
886f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
887875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#define PARAM(a, A) if (a) *a = 0
888efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (design_size, designSize);
889efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_id, subfamilyID);
890efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (subfamily_name_id, subfamilyNameID);
891efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_start, rangeStart);
892efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  PARAM (range_end, rangeEnd);
893875a5cbc9c37f4264241c43b80afad2628eab749Behdad Esfahbod#undef PARAM
894f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod
895efe252e6000558f78075adadb2a3dba25ab67c04Behdad Esfahbod  return false;
896f54cce3c6a0432268ce159dbe6c5c6b7f583b87aBehdad Esfahbod}
897d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
898d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
899d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod/*
900bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod * Parts of different types are implemented here such that they have direct
901d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod * access to GSUB/GPOS lookups.
902d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod */
903d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
904d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
905bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GSUBProxy
906bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
907bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 0;
9086ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod  static const bool inplace = false;
909bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::SubstLookup Lookup;
910bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
911bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy (hb_face_t *face) :
912bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gsub),
913bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
914bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
915bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GSUB &table;
916bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
917bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
918bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
919bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodstruct GPOSProxy
920bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
921bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  static const unsigned int table_index = 1;
9226ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod  static const bool inplace = true;
923bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  typedef OT::PosLookup Lookup;
924bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
925bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy (hb_face_t *face) :
926bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    table (*hb_ot_layout_from_face (face)->gpos),
927bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
928bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
929bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const OT::GPOS &table;
930bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const hb_ot_layout_lookup_accelerator_t *accels;
931bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod};
932bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
933bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
9343e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbodstruct hb_get_subtables_context_t :
9353e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod       OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
9363e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod{
9373e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  template <typename Type>
9383e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c)
9393e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  {
9403e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    const Type *typed_obj = (const Type *) obj;
9413e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    return typed_obj->apply (c);
9423e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  }
9433e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9443e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c);
9453e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9463e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  struct hb_applicable_t
9473e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  {
9483e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    inline void init (const void *obj_, hb_apply_func_t apply_func_)
9493e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    {
9503e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod      obj = obj_;
9513e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod      apply_func = apply_func_;
9523e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    }
9533e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9543e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); }
9553e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9563e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    private:
9573e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    const void *obj;
9583e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    hb_apply_func_t apply_func;
9593e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  };
9603e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9613e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  typedef hb_auto_array_t<hb_applicable_t> array_t;
9623e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9633e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  /* Dispatch interface. */
9643e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  inline const char *get_name (void) { return "GET_SUBTABLES"; }
9653e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  template <typename T>
9663e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  inline return_t dispatch (const T &obj)
9673e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  {
9683e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    hb_applicable_t *entry = array.push();
9693e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    if (likely (entry))
9703e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod      entry->init (&obj, apply_to<T>);
9713e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    return HB_VOID;
9723e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  }
9733e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  static return_t default_return_value (void) { return HB_VOID; }
9743e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
9753e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9763e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  hb_get_subtables_context_t (array_t &array_) :
9773e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod			      array (array_),
9783e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod			      debug_depth (0) {}
9793e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
9803e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  array_t &array;
9813e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  unsigned int debug_depth;
9823e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod};
9833e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
984e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbodstatic inline bool
985e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbodapply_forward (OT::hb_apply_context_t *c,
9863e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	       const hb_ot_layout_lookup_accelerator_t &accel,
9873e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	       const hb_get_subtables_context_t::array_t &subtables)
988e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod{
989e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  bool ret = false;
990e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
991abadc1717d997b69f987fdf1be9e12156d2d13d6Behdad Esfahbod  while (buffer->idx < buffer->len && !buffer->in_error)
992e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  {
9933e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    bool applied = false;
994e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod    if (accel.may_have (buffer->cur().codepoint) &&
995e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod	(buffer->cur().mask & c->lookup_mask) &&
9963e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	c->check_glyph_property (&buffer->cur(), c->lookup_props))
9973e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod     {
9983e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod       for (unsigned int i = 0; i < subtables.len; i++)
9993e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod         if (subtables[i].apply (c))
10003e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	 {
10013e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	   applied = true;
10023e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	   break;
10033e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	 }
10043e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod     }
10053e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
10063e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    if (applied)
1007e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod      ret = true;
1008e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod    else
1009e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod      buffer->next_glyph ();
1010e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  }
1011e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  return ret;
1012e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod}
1013e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod
1014e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbodstatic inline bool
1015e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbodapply_backward (OT::hb_apply_context_t *c,
10163e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	       const hb_ot_layout_lookup_accelerator_t &accel,
10173e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	       const hb_get_subtables_context_t::array_t &subtables)
1018e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod{
1019e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  bool ret = false;
1020e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
1021e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  do
1022e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  {
1023e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod    if (accel.may_have (buffer->cur().codepoint) &&
1024e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod	(buffer->cur().mask & c->lookup_mask) &&
10253e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	c->check_glyph_property (&buffer->cur(), c->lookup_props))
10263e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    {
10273e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod     for (unsigned int i = 0; i < subtables.len; i++)
10283e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod       if (subtables[i].apply (c))
10293e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod       {
10303e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	 ret = true;
10313e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod	 break;
10323e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod       }
10333e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    }
1034e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod    /* The reverse lookup doesn't "advance" cursor (for good reason). */
1035e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod    buffer->idx--;
1036e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod
1037e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  }
1038e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  while ((int) buffer->idx >= 0);
1039e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod  return ret;
1040e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod}
1041e2f50f2a7ebf9882ea89dc3f0c740e7fce964e37Behdad Esfahbod
104245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodtemplate <typename Proxy>
10431d4a328472f094c0d75a062f6e176c6b1875cfdcBehdad Esfahbodstatic inline void
104445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbodapply_string (OT::hb_apply_context_t *c,
104545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	      const typename Proxy::Lookup &lookup,
104645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod	      const hb_ot_layout_lookup_accelerator_t &accel)
104745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod{
1048ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
104945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
10505337db29af39084d677a63154f404eca0c20cfebBehdad Esfahbod  if (unlikely (!buffer->len || !c->lookup_mask))
10511d4a328472f094c0d75a062f6e176c6b1875cfdcBehdad Esfahbod    return;
105245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
10532c8b3b2e5312c9858584f568b1528c57e5bb8a10Behdad Esfahbod  c->set_lookup_props (lookup.get_props ());
105445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
10553e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  hb_get_subtables_context_t::array_t subtables;
10563e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  hb_get_subtables_context_t c_get_subtables (subtables);
10573e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod  lookup.dispatch (&c_get_subtables);
10583e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod
105945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  if (likely (!lookup.is_reverse ()))
106045f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  {
106145f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    /* in/out forward substitution/positioning */
106245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    if (Proxy::table_index == 0)
1063ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->clear_output ();
1064ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    buffer->idx = 0;
106545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
1066640b66c6348653bfd7cf88ea9caa2133c0eb949fBehdad Esfahbod    bool ret;
10673e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    ret = apply_forward (c, accel, subtables);
1068640b66c6348653bfd7cf88ea9caa2133c0eb949fBehdad Esfahbod    if (ret)
10699d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod    {
10706ffc007b61402c9d1d4de368deed4971a10ed00bBehdad Esfahbod      if (!Proxy::inplace)
1071ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod	buffer->swap_buffers ();
10729d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod      else
10731d4a328472f094c0d75a062f6e176c6b1875cfdcBehdad Esfahbod	assert (!buffer->has_separate_output ());
10749d9e72e94e7914f82ce62a304e7242f79c13edafBehdad Esfahbod    }
107545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  }
107645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  else
107745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  {
107845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    /* in-place backward substitution/positioning */
107945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod    if (Proxy::table_index == 0)
1080ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod      buffer->remove_output ();
1081ac8cd511911c7dca6222d14fa758bff75d601567Behdad Esfahbod    buffer->idx = buffer->len - 1;
108245f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
10833e704521f67e021fb51cda7319925fd39eba4f97Behdad Esfahbod    apply_backward (c, accel, subtables);
108445f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  }
108545f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod}
108645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod
1087bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodtemplate <typename Proxy>
1088bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodinline void hb_ot_map_t::apply (const Proxy &proxy,
1089d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				const hb_ot_shape_plan_t *plan,
1090d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_font_t *font,
1091d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod				hb_buffer_t *buffer) const
1092d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
1093bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  const unsigned int table_index = proxy.table_index;
1094d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  unsigned int i = 0;
1095bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  OT::hb_apply_context_t c (table_index, font, buffer);
109645f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
1097d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
1098d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
1099d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    const stage_map_t *stage = &stages[table_index][stage_index];
1100d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    for (; i < stage->last_lookup; i++)
1101bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    {
1102bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      unsigned int lookup_index = lookups[table_index][i].index;
11030475ef2f97e3035a2eea9a0f96031331e07e8e29Behdad Esfahbod      if (!buffer->message (font, "start lookup %d", lookup_index)) continue;
11042c8b3b2e5312c9858584f568b1528c57e5bb8a10Behdad Esfahbod      c.set_lookup_index (lookup_index);
1105bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_lookup_mask (lookups[table_index][i].mask);
1106bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
110745f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod      apply_string<Proxy> (&c,
110845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod			   proxy.table.get_lookup (lookup_index),
110945f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod			   proxy.accels[lookup_index]);
11100475ef2f97e3035a2eea9a0f96031331e07e8e29Behdad Esfahbod      (void) buffer->message (font, "end lookup %d", lookup_index);
1111bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod    }
1112d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
1113d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    if (stage->pause_func)
1114d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    {
1115d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      buffer->clear_output ();
1116d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod      stage->pause_func (plan, font, buffer);
1117d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod    }
1118d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod  }
1119d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
1120d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
1121d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
1122d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
1123bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GSUBProxy proxy (font->face);
1124bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
1125d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
1126d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod
1127d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbodvoid hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
1128d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod{
1129bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  GPOSProxy proxy (font->face);
1130bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  apply (proxy, plan, font, buffer);
1131bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod}
1132bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod
1133bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad EsfahbodHB_INTERNAL void
1134bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbodhb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
1135bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const OT::SubstLookup &lookup,
1136bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod				const hb_ot_layout_lookup_accelerator_t &accel)
1137bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod{
113845f3d980c9503bd94e64f6e3f67f97688347d00cBehdad Esfahbod  apply_string<GSUBProxy> (c, lookup, accel);
1139d2c96819de9a7428b65ef0adf794416224221f36Behdad Esfahbod}
1140