hb-ot-layout.cc revision b9d3f60520c022dc952e65a66eb138d1f7cae2e1
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Copyright © 1998-2004  David Turner and Werner Lemberg
33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Copyright © 2006  Behdad Esfahbod
43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Copyright © 2007,2008,2009  Red Hat, Inc.
53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Copyright © 2012,2013  Google, Inc.
63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *
73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *  This is part of HarfBuzz, a text shaping library.
83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *
93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Permission is hereby granted, without written agreement and without
103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * license or royalty fees, to use, copy, modify, and distribute this
113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * software and its documentation for any purpose, provided that the
123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * above copyright notice and the following two paragraphs appear in
133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * all copies of this software.
143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *
153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * DAMAGE.
207e41fe84a841d7b9d7b36b245b65e9dcb3314943cristy *
213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *
273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Red Hat Author(s): Behdad Esfahbod
283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Google Author(s): Behdad Esfahbod
293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-layout-private.hh"
323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-layout-gdef-table.hh"
343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-layout-gsub-table.hh"
353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-layout-gpos-table.hh"
363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-layout-jstf-table.hh"
373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include "hb-ot-map-private.hh"
393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <stdlib.h>
413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <string.h>
423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
443ed852eea50f9d4cd633efb8c2b054b8e33c253cristyHB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
463ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_t *
473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_hb_ot_layout_create (hb_face_t *face)
483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely (!layout))
513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return NULL;
523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy		(layout->gpos_lookup_count && !layout->gpos_accels)))
703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    _hb_ot_layout_destroy (layout);
723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return NULL;
733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return layout;
813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
833ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_hb_ot_layout_destroy (hb_ot_layout_t *layout)
853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    layout->gsub_accels[i].fini ();
88a20c904a6f3e3a11939d5260485be72d5c849c63cristy  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
89a20c904a6f3e3a11939d5260485be72d5c849c63cristy    layout->gpos_accels[i].fini ();
90b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  free (layout->gsub_accels);
923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  free (layout->gpos_accels);
933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hb_blob_destroy (layout->gdef_blob);
953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hb_blob_destroy (layout->gsub_blob);
963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hb_blob_destroy (layout->gpos_blob);
973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  free (layout);
993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline const OT::GDEF&
1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_get_gdef (hb_face_t *face)
1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
104b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
105a20c904a6f3e3a11939d5260485be72d5c849c63cristy  return *hb_ot_layout_from_face (face)->gdef;
106a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
107a20c904a6f3e3a11939d5260485be72d5c849c63cristystatic inline const OT::GSUB&
108a20c904a6f3e3a11939d5260485be72d5c849c63cristy_get_gsub (hb_face_t *face)
109a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
110b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
111a20c904a6f3e3a11939d5260485be72d5c849c63cristy  return *hb_ot_layout_from_face (face)->gsub;
112a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
113b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristystatic inline const OT::GPOS&
114a20c904a6f3e3a11939d5260485be72d5c849c63cristy_get_gpos (hb_face_t *face)
115b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
116a20c904a6f3e3a11939d5260485be72d5c849c63cristy  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
117a20c904a6f3e3a11939d5260485be72d5c849c63cristy  return *hb_ot_layout_from_face (face)->gpos;
118b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
119a20c904a6f3e3a11939d5260485be72d5c849c63cristy
120a20c904a6f3e3a11939d5260485be72d5c849c63cristy
121b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy/*
122b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy * GDEF
123a20c904a6f3e3a11939d5260485be72d5c849c63cristy */
124b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
125b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_bool_t
126a20c904a6f3e3a11939d5260485be72d5c849c63cristyhb_ot_layout_has_glyph_classes (hb_face_t *face)
127b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
128b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return _get_gdef (face).has_glyph_classes ();
129b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
130b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
131b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_glyph_class_t
132b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_get_glyph_class (hb_face_t      *face,
133b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy			      hb_codepoint_t  glyph)
134b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
135b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
136b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
137b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
138b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyvoid
139b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
140b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  hb_ot_layout_glyph_class_t  klass,
141b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  hb_set_t                   *glyphs /* OUT */)
142b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
143b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
144b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
145b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
146b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyunsigned int
147b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_get_attach_points (hb_face_t      *face,
148b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				hb_codepoint_t  glyph,
149b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				unsigned int    start_offset,
150b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				unsigned int   *point_count /* IN/OUT */,
151b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				unsigned int   *point_array /* OUT */)
152b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
153b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
154b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
155b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
156b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyunsigned int
157b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_get_ligature_carets (hb_font_t      *font,
158b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  hb_direction_t  direction,
159a20c904a6f3e3a11939d5260485be72d5c849c63cristy				  hb_codepoint_t  glyph,
160a20c904a6f3e3a11939d5260485be72d5c849c63cristy				  unsigned int    start_offset,
161a20c904a6f3e3a11939d5260485be72d5c849c63cristy				  unsigned int   *caret_count /* IN/OUT */,
162a20c904a6f3e3a11939d5260485be72d5c849c63cristy				  int            *caret_array /* OUT */)
163a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
164a20c904a6f3e3a11939d5260485be72d5c849c63cristy  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
165a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * GSUB/GPOS
1703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic const OT::GSUBGPOS&
1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristyget_gsubgpos_table (hb_face_t *face,
1743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy		    hb_tag_t   table_tag)
1753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (table_tag) {
1773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GSUB: return _get_gsub (face);
1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GPOS: return _get_gpos (face);
1793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    default:             return OT::Null(OT::GSUBGPOS);
1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
1813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1843ed852eea50f9d4cd633efb8c2b054b8e33c253cristyunsigned int
1853ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_table_get_script_tags (hb_face_t    *face,
1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_tag_t      table_tag,
1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int  start_offset,
1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int *script_count /* IN/OUT */,
1893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_tag_t     *script_tags /* OUT */)
1903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return g.get_script_tags (start_offset, script_count, script_tags);
1943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
1953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
1973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
1983ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
1993ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_table_find_script (hb_face_t    *face,
2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				hb_tag_t      table_tag,
2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				hb_tag_t      script_tag,
202b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				unsigned int *script_index)
203a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
204a20c904a6f3e3a11939d5260485be72d5c849c63cristy  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
205a20c904a6f3e3a11939d5260485be72d5c849c63cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
206a20c904a6f3e3a11939d5260485be72d5c849c63cristy
207a20c904a6f3e3a11939d5260485be72d5c849c63cristy  if (g.find_script_index (script_tag, script_index))
208b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return true;
209b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
210b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try finding 'DFLT' */
211b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
212a20c904a6f3e3a11939d5260485be72d5c849c63cristy    return false;
213b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
214a20c904a6f3e3a11939d5260485be72d5c849c63cristy  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
215b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy   * including many versions of DejaVu Sans Mono! */
216b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
217b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return false;
218b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
219b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try with 'latn'; some old fonts put their features there even though
220b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy     they're really trying to support Thai, for example :( */
221a20c904a6f3e3a11939d5260485be72d5c849c63cristy  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
222a20c904a6f3e3a11939d5260485be72d5c849c63cristy    return false;
223b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
224b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
225b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return false;
226a20c904a6f3e3a11939d5260485be72d5c849c63cristy}
227b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
228b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_bool_t
229b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_table_choose_script (hb_face_t      *face,
230b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  hb_tag_t        table_tag,
231b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  const hb_tag_t *script_tags,
232b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  unsigned int   *script_index,
233b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				  hb_tag_t       *chosen_script)
234b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
235b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
236b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
237b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
238b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  while (*script_tags)
239b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  {
240b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (g.find_script_index (*script_tags, script_index)) {
241b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      if (chosen_script)
242b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy        *chosen_script = *script_tags;
243b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      return true;
244b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    }
245b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    script_tags++;
246b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
247b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
248b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try finding 'DFLT' */
249b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
250b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (chosen_script)
251b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
252b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return false;
253b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
254b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
255b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
256b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
257b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (chosen_script)
258b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
259b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return false;
260b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
261a20c904a6f3e3a11939d5260485be72d5c849c63cristy
262b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try with 'latn'; some old fonts put their features there even though
263b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy     they're really trying to support Thai, for example :( */
264b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
265b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    if (chosen_script)
266b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
267b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return false;
268b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
269b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
270b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
271b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (chosen_script)
272b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
273b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return false;
274b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
275b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
276b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyunsigned int
277b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
278b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				     hb_tag_t      table_tag,
279b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				     unsigned int  start_offset,
280b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				     unsigned int *feature_count /* IN/OUT */,
281b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				     hb_tag_t     *feature_tags /* OUT */)
282b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
283b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
284b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
285b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return g.get_feature_tags (start_offset, feature_count, feature_tags);
286b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
287b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
288b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
289b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyunsigned int
290b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_script_get_language_tags (hb_face_t    *face,
291b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				       hb_tag_t      table_tag,
292b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				       unsigned int  script_index,
293b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				       unsigned int  start_offset,
294b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				       unsigned int *language_count /* IN/OUT */,
295b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				       hb_tag_t     *language_tags /* OUT */)
296b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
297b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
298b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
299b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
300b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
301b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
302b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_bool_t
303b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_script_find_language (hb_face_t    *face,
304b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				   hb_tag_t      table_tag,
305b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				   unsigned int  script_index,
306b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				   hb_tag_t      language_tag,
307b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy				   unsigned int *language_index)
308b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
309b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
310b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
311b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
312b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (s.find_lang_sys_index (language_tag, language_index))
313b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return true;
314b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
315b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
316b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
317b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    return false;
318b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
319b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
320b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return false;
321b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
322b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
323b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_bool_t
324b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
325b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						  hb_tag_t      table_tag,
326b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						  unsigned int  script_index,
327b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						  unsigned int  language_index,
328b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						  unsigned int *feature_index)
329b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
330b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return hb_ot_layout_language_get_required_feature (face,
331b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						     table_tag,
332b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						     script_index,
333b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						     language_index,
334b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						     feature_index,
335b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy						     NULL);
336b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
337b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
338b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_bool_t
339b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_language_get_required_feature (hb_face_t    *face,
340b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					    hb_tag_t      table_tag,
341b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					    unsigned int  script_index,
342b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					    unsigned int  language_index,
343b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					    unsigned int *feature_index,
344b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					    hb_tag_t     *feature_tag)
345b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
346b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
347b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
348b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
349b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  unsigned int index = l.get_required_feature_index ();
350b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (feature_index) *feature_index = index;
351b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  if (feature_tag) *feature_tag = g.get_feature_tag (index);
352b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
353b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  return l.has_required_feature ();
354b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy}
355b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy
356b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyunsigned int
357b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristyhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
358b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy					   hb_tag_t      table_tag,
359a20c904a6f3e3a11939d5260485be72d5c849c63cristy					   unsigned int  script_index,
360a20c904a6f3e3a11939d5260485be72d5c849c63cristy					   unsigned int  language_index,
361a20c904a6f3e3a11939d5260485be72d5c849c63cristy					   unsigned int  start_offset,
362a20c904a6f3e3a11939d5260485be72d5c849c63cristy					   unsigned int *feature_count /* IN/OUT */,
363a20c904a6f3e3a11939d5260485be72d5c849c63cristy					   unsigned int *feature_indexes /* OUT */)
364a20c904a6f3e3a11939d5260485be72d5c849c63cristy{
365a20c904a6f3e3a11939d5260485be72d5c849c63cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristyunsigned int
3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					hb_tag_t      table_tag,
3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int  script_index,
3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int  language_index,
3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int  start_offset,
3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int *feature_count /* IN/OUT */,
3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					hb_tag_t     *feature_tags /* OUT */)
3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (feature_tags) {
3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int count = *feature_count;
3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (unsigned int i = 0; i < count; i++)
3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return ret;
3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_language_find_feature (hb_face_t    *face,
3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_tag_t      table_tag,
3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int  script_index,
4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int  language_index,
4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_tag_t      feature_tag,
4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int *feature_index)
4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int num_features = l.get_feature_count ();
4093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int i = 0; i < num_features; i++) {
4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int f_index = l.get_feature_index (i);
4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (feature_tag == g.get_feature_tag (f_index)) {
4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (feature_index) *feature_index = f_index;
4143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return true;
4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return false;
4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristyunsigned int
423bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyhb_ot_layout_feature_get_lookups (hb_face_t    *face,
4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				  hb_tag_t      table_tag,
4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				  unsigned int  feature_index,
4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				  unsigned int  start_offset,
4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				  unsigned int *lookup_count /* IN/OUT */,
4283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				  unsigned int *lookup_indexes /* OUT */)
4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::Feature &f = g.get_feature (feature_index);
4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristyunsigned int
4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_table_get_lookup_count (hb_face_t    *face,
4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				     hb_tag_t      table_tag)
4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (table_tag)
4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GSUB:
4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return hb_ot_layout_from_face (face)->gsub_lookup_count;
4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GPOS:
4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
4483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return hb_ot_layout_from_face (face)->gpos_lookup_count;
4493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return 0;
4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void
4553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				       hb_tag_t        table_tag,
4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				       unsigned int    feature_index,
458bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy				       hb_set_t       *lookup_indexes /* OUT */)
4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
4603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int lookup_indices[32];
4613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int offset, len;
4623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  offset = 0;
4643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  do {
4653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    len = ARRAY_LENGTH (lookup_indices);
466bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    hb_ot_layout_feature_get_lookups (face,
4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      table_tag,
4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      feature_index,
4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      offset, &len,
4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      lookup_indices);
4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (unsigned int i = 0; i < len; i++)
4733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      lookup_indexes->add (lookup_indices[i]);
474bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy
4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset += len;
4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  } while (len == ARRAY_LENGTH (lookup_indices));
4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
4783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
4793ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void
4803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
4813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					hb_tag_t        table_tag,
4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int    script_index,
4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					unsigned int    language_index,
4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					const hb_tag_t *features,
4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					hb_set_t       *lookup_indexes /* OUT */)
486f84a193d5f435588cd78d521fff3f1f852e227f8cristy{
4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (!features)
4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int required_feature_index;
4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (hb_ot_layout_language_get_required_feature (face,
4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						    table_tag,
4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						    script_index,
4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						    language_index,
4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						    &required_feature_index,
4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						    NULL))
496f84a193d5f435588cd78d521fff3f1f852e227f8cristy      _hb_ot_layout_collect_lookups_lookups (face,
4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     table_tag,
4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     required_feature_index,
499bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy					     lookup_indexes);
5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* All features */
5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int feature_indices[32];
5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int offset, len;
5043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    offset = 0;
5063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    do {
5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      len = ARRAY_LENGTH (feature_indices);
5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      hb_ot_layout_language_get_feature_indexes (face,
5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 table_tag,
5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 script_index,
5113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 language_index,
5123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 offset, &len,
5133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 feature_indices);
5143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      for (unsigned int i = 0; i < len; i++)
5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	_hb_ot_layout_collect_lookups_lookups (face,
5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       table_tag,
5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       feature_indices[i],
519bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy					       lookup_indexes);
5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      offset += len;
5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    } while (len == ARRAY_LENGTH (feature_indices));
5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (; *features; features++)
5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned int feature_index;
5293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (hb_ot_layout_language_find_feature (face,
5303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      table_tag,
5313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      script_index,
5323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      language_index,
5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      *features,
5343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      &feature_index))
5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        _hb_ot_layout_collect_lookups_lookups (face,
5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       table_tag,
5373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       feature_index,
5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       lookup_indexes);
5393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic void
5443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
5453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					 hb_tag_t        table_tag,
5463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					 unsigned int    script_index,
5473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					 const hb_tag_t *languages,
5483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					 const hb_tag_t *features,
5493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					 hb_set_t       *lookup_indexes /* OUT */)
5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
5513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  _hb_ot_layout_collect_lookups_features (face,
5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  table_tag,
553bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy					  script_index,
5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  features,
5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  lookup_indexes);
5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (!languages)
5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* All languages */
561bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    unsigned int count = hb_ot_layout_script_get_language_tags (face,
5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy								table_tag,
5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy								script_index,
5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy								0, NULL, NULL);
5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (unsigned int language_index = 0; language_index < count; language_index++)
5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      _hb_ot_layout_collect_lookups_features (face,
5673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      table_tag,
5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      script_index,
569bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy					      language_index,
5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      features,
5713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					      lookup_indexes);
5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
5733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (; *languages; languages++)
5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned int language_index;
578f84a193d5f435588cd78d521fff3f1f852e227f8cristy      if (hb_ot_layout_script_find_language (face,
5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     table_tag,
5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     script_index,
5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     *languages,
5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					     &language_index))
5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        _hb_ot_layout_collect_lookups_features (face,
5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						table_tag,
5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						script_index,
5863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						language_index,
587f84a193d5f435588cd78d521fff3f1f852e227f8cristy						features,
5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						lookup_indexes);
5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
590bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy  }
5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
5923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_collect_lookups (hb_face_t      *face,
5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      hb_tag_t        table_tag,
5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      const hb_tag_t *scripts,
5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      const hb_tag_t *languages,
5983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      const hb_tag_t *features,
5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      hb_set_t       *lookup_indexes /* OUT */)
6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (!scripts)
6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* All scripts */
6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    unsigned int count = hb_ot_layout_table_get_script_tags (face,
6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy							     table_tag,
6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy							     0, NULL, NULL);
6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (unsigned int script_index = 0; script_index < count; script_index++)
6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      _hb_ot_layout_collect_lookups_languages (face,
6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       table_tag,
6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       script_index,
6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       languages,
6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       features,
6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					       lookup_indexes);
6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  else
6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (; *scripts; scripts++)
6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned int script_index;
6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (hb_ot_layout_table_find_script (face,
6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  table_tag,
6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  *scripts,
6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					  &script_index))
6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        _hb_ot_layout_collect_lookups_languages (face,
6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 table_tag,
6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 script_index,
6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 languages,
6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 features,
6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy						 lookup_indexes);
6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
631b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_tag_t      table_tag,
6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    unsigned int  lookup_index,
6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::hb_collect_glyphs_context_t c (face,
6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				     glyphs_before,
6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				     glyphs_input,
6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				     glyphs_after,
6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				     glyphs_output);
6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  switch (table_tag)
6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GSUB:
6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
6563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      l.collect_glyphs (&c);
6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    case HB_OT_TAG_GPOS:
6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      l.collect_glyphs (&c);
6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      return;
6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * OT::GSUB
6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_has_substitution (hb_face_t *face)
6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return &_get_gsub (face) != &OT::Null(OT::GSUB);
6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_lookup_would_substitute (hb_face_t            *face,
6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      unsigned int          lookup_index,
6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      const hb_codepoint_t *glyphs,
6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      unsigned int          glyphs_length,
6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				      hb_bool_t             zero_context)
6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					   unsigned int          lookup_index,
6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					   const hb_codepoint_t *glyphs,
6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					   unsigned int          glyphs_length,
6953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy					   hb_bool_t             zero_context)
696b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy{
6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
7060157aeadef2fce908277168097a160a8f15a6952cristyhb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::GSUB::substitute_start (font, buffer);
7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
7123ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::GSUB::substitute_finish (font, buffer);
7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				        unsigned int  lookup_index,
7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				        hb_set_t     *glyphs)
7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::hb_closure_context_t c (face, glyphs);
7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  l.closure (&c);
7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * OT::GPOS
7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_has_positioning (hb_face_t *face)
7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return &_get_gpos (face) != &OT::Null(OT::GPOS);
7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::GPOS::position_start (font, buffer);
7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristyvoid
7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::GPOS::position_finish (font, buffer);
7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_bool_t
7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_get_size_params (hb_face_t    *face,
7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      unsigned int *design_size,       /* OUT.  May be NULL */
7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
7563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      unsigned int *range_start,       /* OUT.  May be NULL */
7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			      unsigned int *range_end          /* OUT.  May be NULL */)
7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GPOS &gpos = _get_gpos (face);
7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const hb_tag_t tag = HB_TAG ('s','i','z','e');
7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int num_features = gpos.get_feature_count ();
7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int i = 0; i < num_features; i++)
7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (tag == gpos.get_feature_tag (i))
7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
7673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      const OT::Feature &f = gpos.get_feature (i);
7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (params.designSize)
7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      {
7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PARAM(a, A) if (a) *a = params.A
7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	PARAM (design_size, designSize);
7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	PARAM (subfamily_id, subfamilyID);
7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	PARAM (subfamily_name_id, subfamilyNameID);
7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	PARAM (range_start, rangeStart);
7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	PARAM (range_end, rangeEnd);
7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef PARAM
7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	return true;
7814e1dff661dca8fc9ca6f524eaacb32c0eb5a9d78cristy      }
7824e1dff661dca8fc9ca6f524eaacb32c0eb5a9d78cristy    }
783f84a193d5f435588cd78d521fff3f1f852e227f8cristy  }
7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PARAM(a, A) if (a) *a = 0
7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PARAM (design_size, designSize);
7873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PARAM (subfamily_id, subfamilyID);
7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PARAM (subfamily_name_id, subfamilyNameID);
7893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PARAM (range_start, rangeStart);
7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  PARAM (range_end, rangeEnd);
7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#undef PARAM
7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return false;
7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
7973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/*
7983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * Parts of different types are implemented here such that they have direct
7993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy * access to GSUB/GPOS lookups.
8003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */
8013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristystruct GSUBProxy
8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const unsigned int table_index = 0;
8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  static const bool inplace = false;
8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef OT::SubstLookup Lookup;
8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GSUBProxy (hb_face_t *face) :
8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    table (*hb_ot_layout_from_face (face)->gsub),
811f84a193d5f435588cd78d521fff3f1f852e227f8cristy    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GSUB &table;
8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const hb_ot_layout_lookup_accelerator_t *accels;
8153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy};
8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristystruct GPOSProxy
81841c3c77d6f4e3131bf2be0b35277c086b69ce492cristy{
81941c3c77d6f4e3131bf2be0b35277c086b69ce492cristy  static const unsigned int table_index = 1;
82041c3c77d6f4e3131bf2be0b35277c086b69ce492cristy  static const bool inplace = true;
8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  typedef OT::PosLookup Lookup;
8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GPOSProxy (hb_face_t *face) :
8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    table (*hb_ot_layout_from_face (face)->gpos),
8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const OT::GPOS &table;
8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const hb_ot_layout_lookup_accelerator_t *accels;
8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy};
8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristytemplate <typename Proxy>
8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic inline bool
8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristyapply_string (OT::hb_apply_context_t *c,
8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	      const typename Proxy::Lookup &lookup,
8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	      const hb_ot_layout_lookup_accelerator_t &accel)
8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
8383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  bool ret = false;
8393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  hb_buffer_t *buffer = c->buffer;
8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (unlikely (!buffer->len || !c->lookup_mask))
8423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    return false;
8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c->set_lookup (lookup);
8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  if (likely (!lookup.is_reverse ()))
8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  {
8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* in/out forward substitution/positioning */
849bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    if (Proxy::table_index == 0)
8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      buffer->clear_output ();
8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    buffer->idx = 0;
852bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy
8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    while (buffer->idx < buffer->len)
8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (accel.may_have (buffer->cur().codepoint) &&
8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  (buffer->cur().mask & c->lookup_mask) &&
8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  c->check_glyph_property (&c->buffer->cur(), c->lookup_props) &&
8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  lookup.dispatch (c))
8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	ret = true;
8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	buffer->next_glyph ();
862bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    }
8633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (ret)
8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      if (!Proxy::inplace)
8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	buffer->swap_buffers ();
8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      else
8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy        assert (!buffer->has_separate_output ());
8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
870b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  }
871b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  else
872b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy  {
8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    /* in-place backward substitution/positioning */
8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (Proxy::table_index == 0)
8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      buffer->remove_output ();
876b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    buffer->idx = buffer->len - 1;
8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    do
878b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy    {
879b51dff5c0d16a4c1b69ff683e786cb3b4c467694cristy      if (accel.may_have (buffer->cur().codepoint) &&
8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  (buffer->cur().mask & c->lookup_mask) &&
8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  c->check_glyph_property (&c->buffer->cur(), c->lookup_props) &&
8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	  lookup.dispatch (c))
8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy	ret = true;
8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      /* The reverse lookup doesn't "advance" cursor (for good reason). */
8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      buffer->idx--;
8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    while ((int) buffer->idx >= 0);
8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  return ret;
8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristytemplate <typename Proxy>
8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristyinline void hb_ot_map_t::apply (const Proxy &proxy,
8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				const hb_ot_shape_plan_t *plan,
8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				hb_font_t *font,
8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				hb_buffer_t *buffer) const
8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  const unsigned int table_index = proxy.table_index;
9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  unsigned int i = 0;
9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  OT::hb_apply_context_t c (table_index, font, buffer);
9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
904bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy
9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
9063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    const stage_map_t *stage = &stages[table_index][stage_index];
9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    for (; i < stage->last_lookup; i++)
9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    {
9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      unsigned int lookup_index = lookups[table_index][i].index;
9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      c.set_lookup_mask (lookups[table_index][i].mask);
9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      c.set_auto_zwj (lookups[table_index][i].auto_zwj);
9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      apply_string<Proxy> (&c,
9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			   proxy.table.get_lookup (lookup_index),
9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy			   proxy.accels[lookup_index]);
9153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    if (stage->pause_func)
918bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy    {
9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      buffer->clear_output ();
9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy      stage->pause_func (plan, font, buffer);
9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy    }
9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  }
9239d314ff2c17a77996c05413c2013880387e50f0ecristy}
9249d314ff2c17a77996c05413c2013880387e50f0ecristy
9259d314ff2c17a77996c05413c2013880387e50f0ecristyvoid hb_ot_map_t::substitute (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GSUBProxy proxy (font->face);
9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  apply (proxy, plan, font, buffer);
9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
931bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyvoid hb_ot_map_t::position (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  GPOSProxy proxy (font->face);
9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  apply (proxy, plan, font, buffer);
9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy
937bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristyHB_INTERNAL void
9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristyhb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				const OT::SubstLookup &lookup,
9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy				const hb_ot_layout_lookup_accelerator_t &accel)
9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{
9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy  apply_string<GSUBProxy> (c, lookup, accel);
9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy}
9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy