hb-ot-layout.cc revision 0a4399ca228d244e646abdb3487da0f13b228889
1fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod/*
26f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod * Copyright (C) 1998-2004  David Turner and Werner Lemberg
36f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod * Copyright (C) 2006  Behdad Esfahbod
4ee58aaebd296ea8237516754fd4e825d524b11b7Behdad Esfahbod * Copyright (C) 2007,2008,2009  Red Hat, Inc.
5fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
6c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
7fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
8fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * Permission is hereby granted, without written agreement and without
9fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
10fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * software and its documentation for any purpose, provided that the
11fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * above copyright notice and the following two paragraphs appear in
12fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * all copies of this software.
13fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
14fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * DAMAGE.
19fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
20fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
23fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *
26fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
27fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod */
28fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
29fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#define HB_OT_LAYOUT_CC
30fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
3122da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-ot-layout-private.hh"
32fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
335f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#include "hb-ot-layout-gdef-private.hh"
345f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#include "hb-ot-layout-gsub-private.hh"
355f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#include "hb-ot-layout-gpos-private.hh"
36fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
376f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
38fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include <stdlib.h>
39aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod#include <string.h>
40aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
41fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
420a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbodhb_ot_layout_t *
430a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod_hb_ot_layout_new (hb_face_t *face)
444a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
450a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  /* Remove this object altogether */
460a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
47555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod
48d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF));
49b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  layout->gdef = Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
5070e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
51d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_get_table (face, HB_OT_TAG_GSUB));
52b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  layout->gsub = Sanitizer<GSUB>::lock_instance (layout->gsub_blob);
5370e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
54d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS));
55b435ab7e29c388e3b100f729957319931625a3a8Behdad Esfahbod  layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
560a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod
570a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return layout;
58f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
59f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
6023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
610a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod_hb_ot_layout_free (hb_ot_layout_t *layout)
62fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
6370e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gdef_blob);
6470e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gsub_blob);
6570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gpos_blob);
6670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
6770e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gdef_blob);
6870e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gsub_blob);
6970e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gpos_blob);
70679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod
71679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod  free (layout->new_gdef.klasses);
7223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
73f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
7423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GDEF&
7523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
7623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
770a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return likely (face->ot_layout->gdef) ? *face->ot_layout->gdef : Null(GDEF);
7823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
79f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
8023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GSUB&
8123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
82fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
830a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return likely (face->ot_layout->gsub) ? *face->ot_layout->gsub : Null(GSUB);
84fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
85fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
8623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GPOS&
8723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
882ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
890a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return likely (face->ot_layout->gpos) ? *face->ot_layout->gpos : Null(GPOS);
902ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
912ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
9223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
93590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
94590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
95590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
96590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
97d6aae5f5cad54fc5dac8b0ff10a3921ebda533d4Behdad Esfahbod/* TODO the public class_t is a mess */
9830bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod
99590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
10052ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
101590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
10223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
103590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
104590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
105081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
10623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_has_new_glyph_classes (hb_face_t *face)
107590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
1080a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  return face->ot_layout->new_gdef.len > 0;
109590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
110590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
11123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic unsigned int
11223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_get_glyph_property (hb_face_t      *face,
11330bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod				  hb_codepoint_t  glyph)
114ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod{
115aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  hb_ot_layout_class_t klass;
11623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GDEF &gdef = _get_gdef (face);
117aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
11823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  klass = gdef.get_glyph_class (glyph);
119ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod
1200a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  if (!klass && glyph < face->ot_layout->new_gdef.len)
1210a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod    klass = face->ot_layout->new_gdef.klasses[glyph];
122aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
123aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  switch (klass) {
124aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  default:
125aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::UnclassifiedGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
126aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::BaseGlyph:		return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
127aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::LigatureGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
128aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::ComponentGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
1295130c35e93528bcf3095fee5baf3847589167a58Behdad Esfahbod  case GDEF::MarkGlyph:
13023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod	klass = gdef.get_mark_attachment_type (glyph);
13109c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod	return HB_OT_LAYOUT_GLYPH_CLASS_MARK + (klass << 8);
132aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
133ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod}
134fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
135081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
13623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_check_glyph_property (hb_face_t    *face,
137f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod				    hb_internal_glyph_info_t *ginfo,
13823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod				    unsigned int  lookup_flags,
13923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod				    unsigned int *property_out)
140590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
1414189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  unsigned int property;
1426f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
143f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
14423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint);
145f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  property = ginfo->gproperty;
1464189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property_out)
1474189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    *property_out = property;
1486f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
1494189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  /* Not covered, if, for example, glyph class is ligature and
1501246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod   * lookup_flags includes LookupFlags::IgnoreLigatures
1516f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod   */
152aa87d951739f6beacb66daa235cd033fdcfcadd7Behdad Esfahbod  if (property & lookup_flags & LookupFlag::IgnoreFlags)
1536f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod    return false;
1546f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
1554189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
156590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  {
1571246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    /* If using mark filtering sets, the high short of
1584189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod     * lookup_flags has the set index.
1591246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     */
1601246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    if (lookup_flags & LookupFlag::UseMarkFilteringSet)
16123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod      return _get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint);
1621246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod
1631246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    /* The second byte of lookup_flags has the meaning
1641246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     * "ignore marks of attachment type different than
1651246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     * the attachment type specified."
1661246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     */
1674189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType)
1684189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return (lookup_flags & LookupFlag::MarkAttachmentType) == (property & LookupFlag::MarkAttachmentType);
169590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  }
170590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
1716f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod  return true;
172590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
173590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
174081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
17523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_skip_mark (hb_face_t    *face,
176f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod			 hb_internal_glyph_info_t *ginfo,
17723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod			 unsigned int  lookup_flags,
17823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod			 unsigned int *property_out)
1794189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod{
1804189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  unsigned int property;
1814189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
182f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
18323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint);
184f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  property = ginfo->gproperty;
1854189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property_out)
1864189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    *property_out = property;
1874189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1884189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
1894189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  {
1904189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* Skip mark if lookup_flags includes LookupFlags::IgnoreMarks */
1914189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::IgnoreMarks)
1924189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return true;
1934189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1944189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* If using mark filtering sets, the high short of lookup_flags has the set index. */
1954189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::UseMarkFilteringSet)
19623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod      return !_get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint);
1974189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1984189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* The second byte of lookup_flags has the meaning "ignore marks of attachment type
1994189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod     * different than the attachment type specified." */
2004189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType)
2014189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return (lookup_flags & LookupFlag::MarkAttachmentType) != (property & LookupFlag::MarkAttachmentType);
2024189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  }
2034189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
2044189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  return false;
2054189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod}
2064189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
207081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
20823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_set_glyph_class (hb_face_t                  *face,
2090ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			       hb_codepoint_t              glyph,
2100ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			       hb_ot_layout_glyph_class_t  klass)
211aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod{
21223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  if (HB_OBJECT_IS_INERT (face))
21323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    return;
21423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
2152c80296aa5991ad67483889147f5c84fefe54af2Behdad Esfahbod  /* TODO optimize this? similar to old harfbuzz code for example */
216aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
2170a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = face->ot_layout;
218aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  hb_ot_layout_class_t gdef_klass;
21915164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod  unsigned int len = layout->new_gdef.len;
220aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
22164d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (glyph > 65535))
22230bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod    return;
22330bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod
2242c80296aa5991ad67483889147f5c84fefe54af2Behdad Esfahbod  /* XXX this is not threadsafe */
225aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  if (glyph >= len) {
22637006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod    unsigned int new_len;
227590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    unsigned char *new_klasses;
228aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
229aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    new_len = len == 0 ? 120 : 2 * len;
23037006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod    while (new_len <= glyph)
23137006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod      new_len *= 2;
23237006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod
233f0c7540c4e217a7354072365a7301453d1e25b80Behdad Esfahbod    if (new_len > 65536)
234f0c7540c4e217a7354072365a7301453d1e25b80Behdad Esfahbod      new_len = 65536;
235590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char));
236aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
23764d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (unlikely (!new_klasses))
238aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod      return;
239ce48f03946bef895912019046bdbe62bb1301d0bBehdad Esfahbod
240aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    memset (new_klasses + len, 0, new_len - len);
241aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
242aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    layout->new_gdef.klasses = new_klasses;
243aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    layout->new_gdef.len = new_len;
244aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
245aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
246aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  switch (klass) {
247aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  default:
248aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED:	gdef_klass = GDEF::UnclassifiedGlyph;	break;
249aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH:	gdef_klass = GDEF::BaseGlyph;		break;
250aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE:	gdef_klass = GDEF::LigatureGlyph;	break;
251aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_MARK:		gdef_klass = GDEF::MarkGlyph;		break;
252aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT:	gdef_klass = GDEF::ComponentGlyph;	break;
253aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
254aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
255aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  layout->new_gdef.klasses[glyph] = gdef_klass;
256aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  return;
257aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod}
258590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
259081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
26023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_set_glyph_property (hb_face_t      *face,
2610ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				  hb_codepoint_t  glyph,
2620ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				  unsigned int    property)
26323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{ _hb_ot_layout_set_glyph_class (face, glyph, (hb_ot_layout_glyph_class_t) (property & 0xff)); }
2640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2660ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_glyph_class_t
2670ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
2680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_codepoint_t  glyph)
2690ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
27023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return (hb_ot_layout_glyph_class_t) (_hb_ot_layout_get_glyph_property (face, glyph) & 0xff);
2710ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
2720ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
273590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodvoid
2740ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_set_glyph_class (hb_face_t                 *face,
2750ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_codepoint_t             glyph,
2760ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_ot_layout_glyph_class_t klass)
2770ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
27823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  _hb_ot_layout_set_glyph_class (face, glyph, klass);
2790ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
2800ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2810ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodvoid
2820ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_build_glyph_classes (hb_face_t      *face,
2832d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod				  hb_codepoint_t *glyphs,
284e50c3978d37b2c0d6ddd4ced6a6196f6857cd596Behdad Esfahbod				  unsigned char  *klasses,
285e50c3978d37b2c0d6ddd4ced6a6196f6857cd596Behdad Esfahbod				  uint16_t        count)
286590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
28723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  if (HB_OBJECT_IS_INERT (face))
28823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    return;
28923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
2900a4399ca228d244e646abdb3487da0f13b228889Behdad Esfahbod  hb_ot_layout_t *layout = face->ot_layout;
2910ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
29264d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod  if (unlikely (!count || !glyphs || !klasses))
293590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    return;
294590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
295590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  if (layout->new_gdef.len == 0) {
296555d11273ee4c30e84eda3a78ffadb3ee7da65d0Behdad Esfahbod    layout->new_gdef.klasses = (unsigned char *) calloc (count, sizeof (unsigned char));
297590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    layout->new_gdef.len = count;
298590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  }
299590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
300f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
30123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    _hb_ot_layout_set_glyph_class (face, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]);
302590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
303706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
304e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
3050ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_attach_points (hb_face_t      *face,
30679420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				hb_codepoint_t  glyph,
307e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				unsigned int    start_offset,
30879420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_count /* IN/OUT */,
30979420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod				unsigned int   *point_array /* OUT */)
31079420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod{
311e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
31262964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod}
31362964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod
314e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
31552ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_get_lig_carets (hb_font_t      *font,
31652ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbod			     hb_face_t      *face,
31762964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod			     hb_codepoint_t  glyph,
318e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod			     unsigned int    start_offset,
31962964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod			     unsigned int   *caret_count /* IN/OUT */,
32062964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod			     int            *caret_array /* OUT */)
32162964afcecd96038cfaa8bc2bc931f43ee83be7eBehdad Esfahbod{
322d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  hb_ot_layout_context_t c;
323d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.font = font;
324d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.face = face;
325d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  return _get_gdef (face).get_lig_carets (&c, glyph, start_offset, caret_count, caret_array);
32679420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod}
32779420ad9caf2d5fc94c3693e8292edfa27060b2dBehdad Esfahbod
328706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod/*
329706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod * GSUB/GPOS
330706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod */
331706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
332706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodstatic const GSUBGPOS&
33323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodget_gsubgpos_table (hb_face_t *face,
33423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod		    hb_tag_t   table_tag)
335706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
3360ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  switch (table_tag) {
33723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GSUB: return _get_gsub (face);
33823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    case HB_OT_TAG_GPOS: return _get_gpos (face);
3390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod    default:             return Null(GSUBGPOS);
340706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  }
341706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
342706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
343706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
344e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
345bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_script_tags (hb_face_t    *face,
346bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t      table_tag,
347e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				    unsigned int  start_offset,
348bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    unsigned int *script_count /* IN/OUT */,
349bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				    hb_tag_t     *script_tags /* OUT */)
350706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
35123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
352706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
353e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_script_tags (start_offset, script_count, script_tags);
354706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
355706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
356706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
3570ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_table_find_script (hb_face_t    *face,
3580ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      table_tag,
3590ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				hb_tag_t      script_tag,
3600ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				unsigned int *script_index)
361706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
362b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
36323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
364706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
365706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (g.find_script_index (script_tag, script_index))
366706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return TRUE;
367706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
368706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try finding 'DFLT' */
3698a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
370706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return FALSE;
371706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
372706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
3738a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
3742014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    return FALSE;
3752014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
3762014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
3772014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  return FALSE;
3782014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod}
3792014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
3802014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_bool_t
3812014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbodhb_ot_layout_table_choose_script (hb_face_t      *face,
3822014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  hb_tag_t        table_tag,
3832014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  const hb_tag_t *script_tags,
3842014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod				  unsigned int   *script_index)
3852014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod{
386b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
3872014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
3882014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
3892014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  while (*script_tags)
3902014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  {
3912014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    if (g.find_script_index (*script_tags, script_index))
3922014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod      return TRUE;
3932014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    script_tags++;
3942014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  }
3952014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
3962014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try finding 'DFLT' */
3972014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index))
3982014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod    return FALSE;
3992014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod
4002014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
4012014b8d110231b13e524008282ece7451f1ae9e7Behdad Esfahbod  if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index))
402706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return FALSE;
403706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
404706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
405706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
406706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
407706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
408e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
409bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
410bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
411e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
412bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
413bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
414c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
41523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
416c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
417e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
418c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
419c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
420c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
421e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
422bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
423bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
424bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
425e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
426bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
427bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
428706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
42923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
430706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
431e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
432706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
433706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
434706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
4350ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
4360ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
4370ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
4380ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
4390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
440706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
441b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
44223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
443706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4444a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
445706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return TRUE;
446706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
447706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
4488a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
449706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return FALSE;
450706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4514a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
452706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
4534a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
454706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4554a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
4560ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
4570ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  hb_tag_t      table_tag,
4580ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  script_index,
4590ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  language_index,
4600ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int *feature_index)
4614a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
46223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
463706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4644a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = l.get_required_feature_index ();
465706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4664a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
4674a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
468706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
469e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
470bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
471bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
472bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
473bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
474e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
475bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
476bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
4770ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
47823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4794a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4804a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
481e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
482c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
483c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
484e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
485bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
486bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
487bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
488bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
489e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
490bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
491bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
4920ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
49323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
494c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4954a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
496bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
497e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
498bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
4999897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
5009897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
5019897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
5029897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
5039897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
504bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
505bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
5064a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
5074a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
5084a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
5094a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
5100ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
5110ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
5120ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
5130ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
5140ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
5150ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
5164a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
517b5db4f1e4eefa266a71a28b5496f47ff9d1a81e8Behdad Esfahbod  ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
51823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
5194a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
5204a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
521f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
522f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
5234a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
5244a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
5254a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
5264a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
5274a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      return TRUE;
5284a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
5294a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
530706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
5314a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
532706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
533706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
534c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
535e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
536bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
537bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 hb_tag_t      table_tag,
538bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int  feature_index,
539e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 unsigned int  start_offset,
540bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int *lookup_count /* IN/OUT */,
541bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int *lookup_indexes /* OUT */)
542c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
54323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
544c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod  const Feature &f = g.get_feature (feature_index);
545c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
546e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
547c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
548c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
5492d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5502d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
5512d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod * GSUB
5522d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
5532d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5542d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
5550ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
5560ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
55723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return &_get_gsub (face) != &Null(GSUB);
5580ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
5590ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
5600ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
561468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbodhb_ot_layout_substitute_lookup (hb_face_t    *face,
562468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_buffer_t  *buffer,
563468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				unsigned int  lookup_index,
564468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_mask_t     mask)
5652d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod{
566d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  hb_ot_layout_context_t c;
567d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.font = NULL;
568d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.face = face;
569d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  return _get_gsub (face).substitute_lookup (&c, buffer, lookup_index, mask);
5705a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod}
5715a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod
572bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
5739c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
5749c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod * GPOS
5759c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
5769c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
5779c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
5780ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
5790ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
58023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return &_get_gpos (face) != &Null(GPOS);
5810ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
5820ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
5830ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
58452ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_position_lookup   (hb_font_t    *font,
58552ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbod				hb_face_t    *face,
586468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_buffer_t  *buffer,
587468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				unsigned int  lookup_index,
588468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_mask_t     mask)
5899c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod{
590d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  hb_ot_layout_context_t c;
591d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.font = font;
592d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  c.face = face;
593d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  return _get_gpos (face).position_lookup (&c, buffer, lookup_index, mask);
5949c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod}
5959db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
5969db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
59733d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbodhb_ot_layout_position_finish (hb_font_t    *font HB_UNUSED,
59833d13fdda99acaeffa9600737e8870278d053ebeBehdad Esfahbod			      hb_face_t    *face HB_UNUSED,
5999db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod			      hb_buffer_t  *buffer)
6009db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
6019db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  unsigned int i, j;
6029db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  unsigned int len = hb_buffer_get_length (buffer);
603f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod  hb_internal_glyph_position_t *pos = (hb_internal_glyph_position_t *) hb_buffer_get_glyph_positions (buffer);
6049db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
6059db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* TODO: Vertical */
6069db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
6079db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Handle cursive connections */
6089db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* First handle all left-to-right connections */
6099db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (j = 0; j < len; j++) {
610f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    if (pos[j].cursive_chain > 0)
611f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    {
612f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[j].y_offset += pos[j - pos[j].cursive_chain].y_offset;
613f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[j].cursive_chain = 0;
6149db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    }
6159db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  }
6169db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Then handle all right-to-left connections */
6179db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (i = len; i > 0; i--) {
6189db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    j = i - 1;
619f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    if (pos[j].cursive_chain < 0)
620f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    {
621f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[j].y_offset += pos[j - pos[j].cursive_chain].y_offset;
622f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[j].cursive_chain = 0;
6239db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    }
6249db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  }
6259db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
6269db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Handle attachments */
6279db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (i = 0; i < len; i++)
628f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    if (pos[i].back)
629f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    {
630f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      unsigned int back = i - pos[i].back;
631f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[i].back = 0;
632f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[i].x_offset += pos[back].x_offset;
633f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      pos[i].y_offset += pos[back].y_offset;
634f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod
635f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      if (buffer->direction == HB_DIRECTION_RTL)
636f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	for (j = back + 1; j < i + 1; j++) {
637f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	  pos[i].x_offset += pos[j].x_advance;
638f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	  pos[i].y_offset += pos[j].y_advance;
639f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	}
640f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod      else
641f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	for (j = back; j < i; j++) {
642f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	  pos[i].x_offset -= pos[j].x_advance;
643f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	  pos[i].y_offset -= pos[j].y_advance;
644f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod	}
645f415755fdf011d3fa3b9aad04c38f2255dd7acf8Behdad Esfahbod    }
6469db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
647