15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 1998-2004  David Turner and Werner Lemberg
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2006  Behdad Esfahbod
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007,2008,2009  Red Hat, Inc.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2012  Google, Inc.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-private.hh"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-gdef-table.hh"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-gsub-table.hh"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-gpos-table.hh"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HB_SHAPER_DATA_ENSURE_DECLARE(ot, face)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_t *
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_ot_layout_create (hb_face_t *face)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!layout))
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gdef_blob = OT::Sanitizer<OT::GDEF>::sanitize (face->reference_table (HB_OT_TAG_GDEF));
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gdef = OT::Sanitizer<OT::GDEF>::lock_instance (layout->gdef_blob);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gsub_blob = OT::Sanitizer<OT::GSUB>::sanitize (face->reference_table (HB_OT_TAG_GSUB));
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gsub = OT::Sanitizer<OT::GSUB>::lock_instance (layout->gsub_blob);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS));
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_digests) ||
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(layout->gpos_lookup_count && !layout->gpos_digests)))
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _hb_ot_layout_destroy (layout);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    layout->gsub_digests[i].init ();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    layout->gsub->get_lookup (i).add_coverage (&layout->gsub_digests[i]);
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    layout->gpos_digests[i].init ();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    layout->gpos->get_lookup (i).add_coverage (&layout->gpos_digests[i]);
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return layout;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_ot_layout_destroy (hb_ot_layout_t *layout)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_destroy (layout->gdef_blob);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_destroy (layout->gsub_blob);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  hb_blob_destroy (layout->gpos_blob);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (layout->gsub_digests);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (layout->gpos_digests);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free (layout);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const OT::GDEF&
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_get_gdef (hb_face_t *face)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GDEF);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *hb_ot_layout_from_face (face)->gdef;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const OT::GSUB&
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_get_gsub (hb_face_t *face)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GSUB);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *hb_ot_layout_from_face (face)->gsub;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline const OT::GPOS&
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_get_gpos (hb_face_t *face)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::GPOS);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *hb_ot_layout_from_face (face)->gpos;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GDEF
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_has_glyph_classes (hb_face_t *face)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _get_gdef (face).has_glyph_classes ();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_glyph_class_t
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_get_glyph_class (hb_face_t      *face,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      hb_codepoint_t  glyph)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  hb_ot_layout_glyph_class_t  klass,
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  hb_set_t                   *glyphs /* OUT */)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_get_attach_points (hb_face_t      *face,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_codepoint_t  glyph,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int    start_offset,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int   *point_count /* IN/OUT */,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int   *point_array /* OUT */)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_get_ligature_carets (hb_font_t      *font,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  hb_direction_t  direction,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  hb_codepoint_t  glyph,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  unsigned int    start_offset,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  unsigned int   *caret_count /* IN/OUT */,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  int            *caret_array /* OUT */)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GSUB/GPOS
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const OT::GSUBGPOS&
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)get_gsubgpos_table (hb_face_t *face,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    hb_tag_t   table_tag)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (table_tag) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HB_OT_TAG_GSUB: return _get_gsub (face);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HB_OT_TAG_GPOS: return _get_gpos (face);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:             return OT::Null(OT::GSUBGPOS);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_table_get_script_tags (hb_face_t    *face,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    hb_tag_t      table_tag,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int  start_offset,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int *script_count /* IN/OUT */,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    hb_tag_t     *script_tags /* OUT */)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g.get_script_tags (start_offset, script_count, script_tags);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_table_find_script (hb_face_t    *face,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_tag_t      table_tag,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_tag_t      script_tag,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int *script_index)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (script_tag, script_index))
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try finding 'DFLT' */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try with 'dflt'; MS site has had typos and many fonts use it now :(.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * including many versions of DejaVu Sans Mono! */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /* try with 'latn'; some old fonts put their features there even though
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     they're really trying to support Thai, for example :( */
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_table_choose_script (hb_face_t      *face,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  hb_tag_t        table_tag,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  const hb_tag_t *script_tags,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  unsigned int   *script_index,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  hb_tag_t       *chosen_script)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*script_tags)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (g.find_script_index (*script_tags, script_index)) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (chosen_script)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *chosen_script = *script_tags;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_tags++;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try finding 'DFLT' */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (chosen_script)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *chosen_script = HB_OT_TAG_DEFAULT_SCRIPT;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (chosen_script)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *chosen_script = HB_OT_TAG_DEFAULT_LANGUAGE;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try with 'latn'; some old fonts put their features there even though
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     they're really trying to support Thai, for example :( */
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index)) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (chosen_script)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *chosen_script = HB_OT_TAG_LATIN_SCRIPT;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chosen_script)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     hb_tag_t      table_tag,
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     unsigned int  start_offset,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     unsigned int *feature_count /* IN/OUT */,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     hb_tag_t     *feature_tags /* OUT */)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g.get_feature_tags (start_offset, feature_count, feature_tags);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_script_get_language_tags (hb_face_t    *face,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       hb_tag_t      table_tag,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       unsigned int  script_index,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       unsigned int  start_offset,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       unsigned int *language_count /* IN/OUT */,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       hb_tag_t     *language_tags /* OUT */)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_script_find_language (hb_face_t    *face,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   hb_tag_t      table_tag,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int  script_index,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   hb_tag_t      language_tag,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int *language_index)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s.find_lang_sys_index (language_tag, language_index))
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						  hb_tag_t      table_tag,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						  unsigned int  script_index,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						  unsigned int  language_index,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						  unsigned int *feature_index)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feature_index) *feature_index = l.get_required_feature_index ();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l.has_required_feature ();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   hb_tag_t      table_tag,
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int  script_index,
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int  language_index,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int  start_offset,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_count /* IN/OUT */,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_indexes /* OUT */)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					hb_tag_t      table_tag,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					unsigned int  script_index,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					unsigned int  language_index,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					unsigned int  start_offset,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					unsigned int *feature_count /* IN/OUT */,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					hb_tag_t     *feature_tags /* OUT */)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feature_tags) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = *feature_count;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_language_find_feature (hb_face_t    *face,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    hb_tag_t      table_tag,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int  script_index,
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int  language_index,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    hb_tag_t      feature_tag,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    unsigned int *feature_index)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int num_features = l.get_feature_count ();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < num_features; i++) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int f_index = l.get_feature_index (i);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (feature_tag == g.get_feature_tag (f_index)) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (feature_index) *feature_index = f_index;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_feature_get_lookups (hb_face_t    *face,
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  hb_tag_t      table_tag,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  unsigned int  feature_index,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  unsigned int  start_offset,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  unsigned int *lookup_count /* IN/OUT */,
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				  unsigned int *lookup_indexes /* OUT */)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::Feature &f = g.get_feature (feature_index);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				       hb_tag_t        table_tag,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				       unsigned int    feature_index,
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				       hb_set_t       *lookup_indexes /* OUT */)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int lookup_indices[32];
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int offset, len;
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  offset = 0;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    len = ARRAY_LENGTH (lookup_indices);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_ot_layout_feature_get_lookups (face,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				      table_tag,
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				      feature_index,
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				      offset, &len,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				      lookup_indices);
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < len; i++)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      lookup_indexes->add (lookup_indices[i]);
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    offset += len;
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (len == ARRAY_LENGTH (lookup_indices));
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					hb_tag_t        table_tag,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					unsigned int    script_index,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					unsigned int    language_index,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					const hb_tag_t *features,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					hb_set_t       *lookup_indexes /* OUT */)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int required_feature_index;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (hb_ot_layout_language_get_required_feature_index (face,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							table_tag,
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							script_index,
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							language_index,
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							&required_feature_index))
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    _hb_ot_layout_collect_lookups_lookups (face,
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					   table_tag,
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					   required_feature_index,
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					   lookup_indexes);
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!features)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* All features */
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int feature_indices[32];
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int offset, len;
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    offset = 0;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    do {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      len = ARRAY_LENGTH (feature_indices);
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hb_ot_layout_language_get_feature_indexes (face,
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 table_tag,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 script_index,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 language_index,
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 offset, &len,
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 feature_indices);
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (unsigned int i = 0; i < len; i++)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	_hb_ot_layout_collect_lookups_lookups (face,
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       table_tag,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       feature_indices[i],
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       lookup_indexes);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      offset += len;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } while (len == ARRAY_LENGTH (feature_indices));
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (; *features; features++)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned int feature_index;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (hb_ot_layout_language_find_feature (face,
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      table_tag,
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      script_index,
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      language_index,
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      *features,
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      &feature_index))
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        _hb_ot_layout_collect_lookups_lookups (face,
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       table_tag,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       feature_index,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       lookup_indexes);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 hb_tag_t        table_tag,
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 unsigned int    script_index,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 const hb_tag_t *languages,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 const hb_tag_t *features,
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 hb_set_t       *lookup_indexes /* OUT */)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _hb_ot_layout_collect_lookups_features (face,
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  table_tag,
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  script_index,
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  features,
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  lookup_indexes);
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!languages)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* All languages */
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = hb_ot_layout_script_get_language_tags (face,
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)								table_tag,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)								script_index,
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)								0, NULL, NULL);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int language_index = 0; language_index < count; language_index++)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _hb_ot_layout_collect_lookups_features (face,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      table_tag,
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      script_index,
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      language_index,
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      features,
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					      lookup_indexes);
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (; *languages; languages++)
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned int language_index;
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (hb_ot_layout_script_find_language (face,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					     table_tag,
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					     script_index,
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					     *languages,
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					     &language_index))
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        _hb_ot_layout_collect_lookups_features (face,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						table_tag,
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						script_index,
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						language_index,
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						features,
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						lookup_indexes);
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_collect_lookups (hb_face_t      *face,
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      hb_tag_t        table_tag,
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      const hb_tag_t *scripts,
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      const hb_tag_t *languages,
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      const hb_tag_t *features,
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      hb_set_t       *lookup_indexes /* OUT */)
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!scripts)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* All scripts */
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = hb_ot_layout_table_get_script_tags (face,
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							     table_tag,
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)							     0, NULL, NULL);
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int script_index = 0; script_index < count; script_index++)
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      _hb_ot_layout_collect_lookups_languages (face,
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       table_tag,
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       script_index,
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       languages,
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       features,
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					       lookup_indexes);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (; *scripts; scripts++)
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned int script_index;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (hb_ot_layout_table_find_script (face,
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  table_tag,
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  *scripts,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					  &script_index))
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        _hb_ot_layout_collect_lookups_languages (face,
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 table_tag,
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 script_index,
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 languages,
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 features,
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)						 lookup_indexes);
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    hb_tag_t      table_tag,
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    unsigned int  lookup_index,
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    hb_set_t     *glyphs_before, /* OUT. May be NULL */
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    hb_set_t     *glyphs_output  /* OUT. May be NULL */)
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OT::hb_collect_glyphs_context_t c (face,
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				     glyphs_before,
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				     glyphs_input,
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				     glyphs_after,
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				     glyphs_output);
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (table_tag)
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case HB_OT_TAG_GSUB:
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      l.collect_glyphs_lookup (&c);
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case HB_OT_TAG_GPOS:
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      l.collect_glyphs_lookup (&c);
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OT::GSUB
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_has_substitution (hb_face_t *face)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &_get_gsub (face) != &OT::Null(OT::GSUB);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      unsigned int          lookup_index,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      const hb_codepoint_t *glyphs,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      unsigned int          glyphs_length,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				      hb_bool_t             zero_context)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int          lookup_index,
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   const hb_codepoint_t *glyphs,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int          glyphs_length,
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   hb_bool_t             zero_context)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OT::GSUB::substitute_start (font, buffer);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_substitute_lookup (hb_font_t    *font,
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_buffer_t  *buffer,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int  lookup_index,
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				hb_mask_t     mask,
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				hb_bool_t     auto_zwj)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gsub_lookup_count)) return false;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OT::hb_apply_context_t c (0, font, buffer, mask, auto_zwj);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::SubstLookup& l = hb_ot_layout_from_face (font->face)->gsub->get_lookup (lookup_index);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gsub_digests[lookup_index]);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OT::GSUB::substitute_finish (font, buffer);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				        unsigned int  lookup_index,
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				        hb_set_t     *glyphs)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OT::hb_closure_context_t c (face, glyphs);
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  l.closure (&c);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OT::GPOS
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_has_positioning (hb_face_t *face)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &_get_gpos (face) != &OT::Null(OT::GPOS);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OT::GPOS::position_start (font, buffer);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_ot_layout_position_lookup (hb_font_t    *font,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      hb_buffer_t  *buffer,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      unsigned int  lookup_index,
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			      hb_mask_t     mask,
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			      hb_bool_t     auto_zwj)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (unlikely (lookup_index >= hb_ot_layout_from_face (font->face)->gpos_lookup_count)) return false;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OT::hb_apply_context_t c (1, font, buffer, mask, auto_zwj);
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const OT::PosLookup& l = hb_ot_layout_from_face (font->face)->gpos->get_lookup (lookup_index);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return l.apply_string (&c, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OT::GPOS::position_finish (font, buffer);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_bool_t
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)hb_ot_layout_get_size_params (hb_face_t    *face,
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      unsigned int *design_size,       /* OUT.  May be NULL */
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      unsigned int *subfamily_id,      /* OUT.  May be NULL */
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      unsigned int *subfamily_name_id, /* OUT.  May be NULL */
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      unsigned int *range_start,       /* OUT.  May be NULL */
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			      unsigned int *range_end          /* OUT.  May be NULL */)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const OT::GPOS &gpos = _get_gpos (face);
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const hb_tag_t tag = HB_TAG ('s','i','z','e');
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned int num_features = gpos.get_feature_count ();
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned int i = 0; i < num_features; i++)
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tag == gpos.get_feature_tag (i))
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const OT::Feature &f = gpos.get_feature (i);
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (params.designSize)
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define PARAM(a, A) if (a) *a = params.A
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PARAM (design_size, designSize);
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PARAM (subfamily_id, subfamilyID);
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PARAM (subfamily_name_id, subfamilyNameID);
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PARAM (range_start, rangeStart);
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PARAM (range_end, rangeEnd);
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#undef PARAM
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return true;
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define PARAM(a, A) if (a) *a = 0
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PARAM (design_size, designSize);
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PARAM (subfamily_id, subfamilyID);
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PARAM (subfamily_name_id, subfamilyNameID);
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PARAM (range_start, rangeStart);
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PARAM (range_end, rangeEnd);
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#undef PARAM
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
787