hb-ot-layout.cc revision 52ea47767c7c35650ebddfba6ddc8203a3e33d3a
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 *
6fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod *  This is part of HarfBuzz, an OpenType Layout engine 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
31fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod#include "hb-ot-layout-private.h"
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
420ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodvoid
4370e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod_hb_ot_layout_init (hb_face_t *face)
444a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
4570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_ot_layout_t *layout = &face->ot_layout;
4670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
47d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gdef_blob = Sanitizer<GDEF>::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF));
48d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gdef = &Sanitizer<GDEF>::lock_instance (layout->gdef_blob);
4970e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
50d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gsub_blob = Sanitizer<GSUB>::sanitize (hb_face_get_table (face, HB_OT_TAG_GSUB));
51d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gsub = &Sanitizer<GSUB>::lock_instance (layout->gsub_blob);
5270e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
53d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS));
54d60bb8ca2ae6edf29b2227b56c57f0d16879370bBehdad Esfahbod  layout->gpos = &Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
55f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod}
56f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
5723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodvoid
5870e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod_hb_ot_layout_fini (hb_face_t *face)
59fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
6070e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_ot_layout_t *layout = &face->ot_layout;
61fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
6270e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gdef_blob);
6370e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gsub_blob);
6470e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_unlock (layout->gpos_blob);
6570e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod
6670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gdef_blob);
6770e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gsub_blob);
6870e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  hb_blob_destroy (layout->gpos_blob);
69679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod
70679f41fe61242aa8d7f45b64bdb66395aa530fe2Behdad Esfahbod  free (layout->new_gdef.klasses);
7123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
72f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
7323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GDEF&
7423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gdef (hb_face_t *face)
7523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{
7670e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  return HB_LIKELY (face->ot_layout.gdef) ? *face->ot_layout.gdef : Null(GDEF);
7723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod}
78f9cd1014f8f4d0394b5e0e9eefc1e2af13c59cabBehdad Esfahbod
7923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GSUB&
8023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gsub (hb_face_t *face)
81fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod{
8270e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  return HB_LIKELY (face->ot_layout.gsub) ? *face->ot_layout.gsub : Null(GSUB);
83fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod}
84fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
8523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic const GPOS&
8623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_get_gpos (hb_face_t *face)
872ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod{
8870e0f2a75ec1559f2f70ada837ce4bc4baca49e3Behdad Esfahbod  return HB_LIKELY (face->ot_layout.gpos) ? *face->ot_layout.gpos : Null(GPOS);
892ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod}
902ebb89d63dd27e800f2b6cbf624924601105f48aBehdad Esfahbod
9123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
92590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod/*
93590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod * GDEF
94590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod */
95590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
96d6aae5f5cad54fc5dac8b0ff10a3921ebda533d4Behdad Esfahbod/* TODO the public class_t is a mess */
9730bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod
98590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodhb_bool_t
9952ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_has_glyph_classes (hb_face_t *face)
100590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
10123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gdef (face).has_glyph_classes ();
102590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
103590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
104081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
10523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_has_new_glyph_classes (hb_face_t *face)
106590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
10723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return face->ot_layout.new_gdef.len > 0;
108590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
109590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
11023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbodstatic unsigned int
11123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_get_glyph_property (hb_face_t      *face,
11230bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod				  hb_codepoint_t  glyph)
113ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod{
114aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  hb_ot_layout_class_t klass;
11523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GDEF &gdef = _get_gdef (face);
116aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
11723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  klass = gdef.get_glyph_class (glyph);
118ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod
11923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  if (!klass && glyph < face->ot_layout.new_gdef.len)
12023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    klass = face->ot_layout.new_gdef.klasses[glyph];
121aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
122aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  switch (klass) {
123aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  default:
124aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::UnclassifiedGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
125aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::BaseGlyph:		return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
126aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::LigatureGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
127aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case GDEF::ComponentGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
1285130c35e93528bcf3095fee5baf3847589167a58Behdad Esfahbod  case GDEF::MarkGlyph:
12923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod	klass = gdef.get_mark_attachment_type (glyph);
13009c292e3b688a67fbae67b645d1e6ffcf8d8eb6eBehdad Esfahbod	return HB_OT_LAYOUT_GLYPH_CLASS_MARK + (klass << 8);
131aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
132ead428d7a0bf4dc84340a99f3959e5cc58123e99Behdad Esfahbod}
133fd92a3dde32fd10df30c9eeb97641bc3c15b1e9bBehdad Esfahbod
134081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
13523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_check_glyph_property (hb_face_t    *face,
136f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod				    hb_internal_glyph_info_t *ginfo,
13723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod				    unsigned int  lookup_flags,
13823c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod				    unsigned int *property_out)
139590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod{
1404189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  unsigned int property;
1416f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
142f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
14323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint);
144f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  property = ginfo->gproperty;
1454189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property_out)
1464189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    *property_out = property;
1476f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
1484189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  /* Not covered, if, for example, glyph class is ligature and
1491246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod   * lookup_flags includes LookupFlags::IgnoreLigatures
1506f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod   */
151aa87d951739f6beacb66daa235cd033fdcfcadd7Behdad Esfahbod  if (property & lookup_flags & LookupFlag::IgnoreFlags)
1526f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod    return false;
1536f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod
1544189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
155590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  {
1561246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    /* If using mark filtering sets, the high short of
1574189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod     * lookup_flags has the set index.
1581246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     */
1591246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    if (lookup_flags & LookupFlag::UseMarkFilteringSet)
16023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod      return _get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint);
1611246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod
1621246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod    /* The second byte of lookup_flags has the meaning
1631246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     * "ignore marks of attachment type different than
1641246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     * the attachment type specified."
1651246e41021ab1d782b4c97e5d81c4917a57e3ed4Behdad Esfahbod     */
1664189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType)
1674189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return (lookup_flags & LookupFlag::MarkAttachmentType) == (property & LookupFlag::MarkAttachmentType);
168590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  }
169590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
1706f425b11799aa20dab553085f05744191b7318e2Behdad Esfahbod  return true;
171590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod}
172590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
173081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodhb_bool_t
17423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_skip_mark (hb_face_t    *face,
175f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod			 hb_internal_glyph_info_t *ginfo,
17623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod			 unsigned int  lookup_flags,
17723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod			 unsigned int *property_out)
1784189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod{
1794189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  unsigned int property;
1804189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
181f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
18223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint);
183f1322e52d557726baa010be8d35a594748e8fa1aBehdad Esfahbod  property = ginfo->gproperty;
1844189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property_out)
1854189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    *property_out = property;
1864189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1874189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)
1884189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  {
1894189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* Skip mark if lookup_flags includes LookupFlags::IgnoreMarks */
1904189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::IgnoreMarks)
1914189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return true;
1924189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1934189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* If using mark filtering sets, the high short of lookup_flags has the set index. */
1944189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::UseMarkFilteringSet)
19523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod      return !_get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint);
1964189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
1974189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    /* The second byte of lookup_flags has the meaning "ignore marks of attachment type
1984189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod     * different than the attachment type specified." */
1994189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod    if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType)
2004189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod      return (lookup_flags & LookupFlag::MarkAttachmentType) != (property & LookupFlag::MarkAttachmentType);
2014189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  }
2024189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
2034189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod  return false;
2044189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod}
2054189b92aaa41e4a1756c561cc6e08b0ed024afdaBehdad Esfahbod
206081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
20723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_set_glyph_class (hb_face_t                  *face,
2080ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			       hb_codepoint_t              glyph,
2090ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			       hb_ot_layout_glyph_class_t  klass)
210aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod{
21123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  if (HB_OBJECT_IS_INERT (face))
21223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod    return;
21323c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod
2142c80296aa5991ad67483889147f5c84fefe54af2Behdad Esfahbod  /* TODO optimize this? similar to old harfbuzz code for example */
215aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
21623c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  hb_ot_layout_t *layout = &face->ot_layout;
217aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  hb_ot_layout_class_t gdef_klass;
21815164d9258a74122a4db748d35532bd72c47cec2Behdad Esfahbod  unsigned int len = layout->new_gdef.len;
219aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
2204acaffd786a11b5bd7d41b39fc65625fd8cd5077Behdad Esfahbod  if (HB_UNLIKELY (glyph > 65535))
22130bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod    return;
22230bd763fa2fa4aceee51433ec9fc8dc28480b5d7Behdad Esfahbod
2232c80296aa5991ad67483889147f5c84fefe54af2Behdad Esfahbod  /* XXX this is not threadsafe */
224aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  if (glyph >= len) {
22537006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod    unsigned int new_len;
226590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    unsigned char *new_klasses;
227aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
228aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    new_len = len == 0 ? 120 : 2 * len;
22937006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod    while (new_len <= glyph)
23037006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod      new_len *= 2;
23137006bd1bd107ac1a1c1b131579e9c494ba3a20fBehdad Esfahbod
232f0c7540c4e217a7354072365a7301453d1e25b80Behdad Esfahbod    if (new_len > 65536)
233f0c7540c4e217a7354072365a7301453d1e25b80Behdad Esfahbod      new_len = 65536;
234590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char));
235aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
2364acaffd786a11b5bd7d41b39fc65625fd8cd5077Behdad Esfahbod    if (HB_UNLIKELY (!new_klasses))
237aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod      return;
238ce48f03946bef895912019046bdbe62bb1301d0bBehdad Esfahbod
239aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    memset (new_klasses + len, 0, new_len - len);
240aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
241aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    layout->new_gdef.klasses = new_klasses;
242aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod    layout->new_gdef.len = new_len;
243aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
244aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
245aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  switch (klass) {
246aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  default:
247aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED:	gdef_klass = GDEF::UnclassifiedGlyph;	break;
248aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH:	gdef_klass = GDEF::BaseGlyph;		break;
249aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE:	gdef_klass = GDEF::LigatureGlyph;	break;
250aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_MARK:		gdef_klass = GDEF::MarkGlyph;		break;
251aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT:	gdef_klass = GDEF::ComponentGlyph;	break;
252aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  }
253aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod
254aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  layout->new_gdef.klasses[glyph] = gdef_klass;
255aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod  return;
256aff831ed6787abe8e24a977e34d97ff2e0b7dc21Behdad Esfahbod}
257590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
258081819ea8b98c0a4b4dffe8d4aca3512f9798719Behdad Esfahbodvoid
25923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod_hb_ot_layout_set_glyph_property (hb_face_t      *face,
2600ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				  hb_codepoint_t  glyph,
2610ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				  unsigned int    property)
26223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod{ _hb_ot_layout_set_glyph_class (face, glyph, (hb_ot_layout_glyph_class_t) (property & 0xff)); }
2630ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2650ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_glyph_class_t
2660ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_get_glyph_class (hb_face_t      *face,
2670ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_codepoint_t  glyph)
2680ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
26923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return (hb_ot_layout_glyph_class_t) (_hb_ot_layout_get_glyph_property (face, glyph) & 0xff);
2700ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
2710ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
272590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbodvoid
2730ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_set_glyph_class (hb_face_t                 *face,
2740ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_codepoint_t             glyph,
2750ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod			      hb_ot_layout_glyph_class_t klass)
2760ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
27723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  _hb_ot_layout_set_glyph_class (face, glyph, klass);
2780ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
2790ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2800ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodvoid
2810ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_build_glyph_classes (hb_face_t      *face,
282e50c3978d37b2c0d6ddd4ced6a6196f6857cd596Behdad Esfahbod				  uint16_t        num_total_glyphs,
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
29023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  hb_ot_layout_t *layout = &face->ot_layout;
2910ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
2924acaffd786a11b5bd7d41b39fc65625fd8cd5077Behdad Esfahbod  if (HB_UNLIKELY (!count || !glyphs || !klasses))
293590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    return;
294590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod
295590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod  if (layout->new_gdef.len == 0) {
296590d55cbb9e21ef74dfd88eee51fd0a763958cd2Behdad Esfahbod    layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, 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{
3220ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  hb_ot_layout_context_t context;
3230ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  context.font = font;
32423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  context.face = face;
325e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return _get_gdef (face).get_lig_carets (&context, 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{
3624a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  ASSERT_STATIC (NO_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))
374706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return FALSE;
375706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
376706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
377706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
378706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
379706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
380e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
381bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_table_get_feature_tags (hb_face_t    *face,
382bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t      table_tag,
383e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				     unsigned int  start_offset,
384bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     unsigned int *feature_count /* IN/OUT */,
385bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				     hb_tag_t     *feature_tags /* OUT */)
386c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
38723c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
388c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
389e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return g.get_feature_tags (start_offset, feature_count, feature_tags);
390c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
391c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
392c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
393e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
394bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_script_get_language_tags (hb_face_t    *face,
395bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t      table_tag,
396bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int  script_index,
397e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int  start_offset,
398bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       unsigned int *language_count /* IN/OUT */,
399bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod				       hb_tag_t     *language_tags /* OUT */)
400706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
40123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
402706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
403e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return s.get_lang_sys_tags (start_offset, language_count, language_tags);
404706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
405706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
406706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbodhb_bool_t
4070ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_script_find_language (hb_face_t    *face,
4080ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      table_tag,
4090ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int  script_index,
4100ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   hb_tag_t      language_tag,
4110ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				   unsigned int *language_index)
412706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod{
4134a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
41423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
415706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4164a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (s.find_lang_sys_index (language_tag, language_index))
417706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return TRUE;
418706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
419706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
4208a3511ac6c795226699c2b36e03401ecdf88f5f8Behdad Esfahbod  if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
421706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod    return FALSE;
422706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4234a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
424706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
4254a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
426706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4274a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
4280ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
4290ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  hb_tag_t      table_tag,
4300ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  script_index,
4310ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int  language_index,
4320ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod						  unsigned int *feature_index)
4334a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
43423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index);
435706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4364a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = l.get_required_feature_index ();
437706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
4384a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  return l.has_required_feature ();
4394a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
440706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
441e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
442bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
443bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   hb_tag_t      table_tag,
444bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  script_index,
445bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int  language_index,
446e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					   unsigned int  start_offset,
447bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_count /* IN/OUT */,
448bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					   unsigned int *feature_indexes /* OUT */)
4490ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
45023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4514a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4524a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
453e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
454c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
455c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
456e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
457bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_language_get_feature_tags (hb_face_t    *face,
458bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t      table_tag,
459bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  script_index,
460bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int  language_index,
461e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int  start_offset,
462bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
463bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */)
4640ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
46523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
466c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4674a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
468bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t));
469e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags);
470bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
4719897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  if (feature_tags) {
4729897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    unsigned int count = *feature_count;
4739897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod    for (unsigned int i = 0; i < count; i++)
4749897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod      feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
4759897749113f76dc26a83bfae8de62e55d384fcadBehdad Esfahbod  }
476bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
477bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  return ret;
4784a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod}
4794a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4804a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4814a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbodhb_bool_t
4820ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_language_find_feature (hb_face_t    *face,
4830ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      table_tag,
4840ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  script_index,
4850ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int  language_index,
4860ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    hb_tag_t      feature_tag,
4870ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod				    unsigned int *feature_index)
4884a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod{
4894a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
49023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
4914a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
4924a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
493f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  unsigned int num_features = l.get_feature_count ();
494f4c9514935cf97a58dcb3b1962ac3f3b5ba61264Behdad Esfahbod  for (unsigned int i = 0; i < num_features; i++) {
4954a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    unsigned int f_index = l.get_feature_index (i);
4964a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod
4974a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    if (feature_tag == g.get_feature_tag (f_index)) {
4984a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      if (feature_index) *feature_index = f_index;
4994a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod      return TRUE;
5004a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod    }
5014a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  }
502706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod
5034a26ea408c87f0bb59deca9ff44008d138471aa3Behdad Esfahbod  if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
504706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod  return FALSE;
505706ab25a4cb043d46e6088aa0a7184ee200276c9Behdad Esfahbod}
506c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
507e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbodunsigned int
508bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbodhb_ot_layout_feature_get_lookup_indexes (hb_face_t    *face,
509bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 hb_tag_t      table_tag,
510bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int  feature_index,
511e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					 unsigned int  start_offset,
512bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int *lookup_count /* IN/OUT */,
513bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod					 unsigned int *lookup_indexes /* OUT */)
514c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod{
51523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  const GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
516c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod  const Feature &f = g.get_feature (feature_index);
517c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
518e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
519c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod}
520c44733596c6648e209c12349e18e35424edf3d59Behdad Esfahbod
5212d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5222d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod/*
5232d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod * GSUB
5242d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod */
5252d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod
5262d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbodhb_bool_t
5270ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_substitution (hb_face_t *face)
5280ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
52923c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return &_get_gsub (face) != &Null(GSUB);
5300ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
5310ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
5320ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
533468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbodhb_ot_layout_substitute_lookup (hb_face_t    *face,
534468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_buffer_t  *buffer,
535468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				unsigned int  lookup_index,
536468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_mask_t     mask)
5372d15e72c75931398db5e027e660f1320bb979117Behdad Esfahbod{
5380ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  hb_ot_layout_context_t context;
5390ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  context.font = NULL;
54023c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  context.face = face;
54123c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gsub (face).substitute_lookup (&context, buffer, lookup_index, mask);
5425a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod}
5435a0b791184cf6ef39eae0570e14aca21abc32845Behdad Esfahbod
544bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
5459c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod/*
5469c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod * GPOS
5479c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod */
5489c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod
5499c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbodhb_bool_t
5500ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_ot_layout_has_positioning (hb_face_t *face)
5510ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod{
55223c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return &_get_gpos (face) != &Null(GPOS);
5530ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod}
5540ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod
5550ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbodhb_bool_t
55652ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_position_lookup   (hb_font_t    *font,
55752ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbod				hb_face_t    *face,
558468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_buffer_t  *buffer,
559468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				unsigned int  lookup_index,
560468769b8f5332940278244e744ec2bd5a5dc5ee9Behdad Esfahbod				hb_mask_t     mask)
5619c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod{
5620ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  hb_ot_layout_context_t context;
5630ead481a5a8623103565fd7d924666e7342278ddBehdad Esfahbod  context.font = font;
56423c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  context.face = face;
56523c86aa0009324433e78fcd0c47f2c0ff14b1949Behdad Esfahbod  return _get_gpos (face).position_lookup (&context, buffer, lookup_index, mask);
5669c42f05a5ccbb48a9367b80ecdf3679e88088fcfBehdad Esfahbod}
5679db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
5689db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbodvoid
56952ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbodhb_ot_layout_position_finish (hb_font_t    *font,
57052ea47767c7c35650ebddfba6ddc8203a3e33d3aBehdad Esfahbod			      hb_face_t    *face,
5719db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod			      hb_buffer_t  *buffer)
5729db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod{
5739db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  unsigned int i, j;
5749db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  unsigned int len = hb_buffer_get_length (buffer);
5759db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  hb_internal_glyph_position_t *positions = (hb_internal_glyph_position_t *) hb_buffer_get_glyph_positions (buffer);
5769db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
5779db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* TODO: Vertical */
5789db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
5799db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Handle cursive connections */
5809db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* First handle all left-to-right connections */
5819db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (j = 0; j < len; j++) {
5829db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    if (positions[j].cursive_chain > 0) {
5839db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      positions[j].y_offset += positions[j - positions[j].cursive_chain].y_offset;
5849db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      positions[j].cursive_chain = 0;
5859db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    }
5869db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  }
5879db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Then handle all right-to-left connections */
5889db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (i = len; i > 0; i--) {
5899db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    j = i - 1;
5909db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    if (positions[j].cursive_chain < 0) {
5919db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      positions[j].y_offset += positions[j - positions[j].cursive_chain].y_offset;
5929db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      positions[j].cursive_chain = 0;
5939db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    }
5949db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  }
5959db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
5969db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  /* Handle attachments */
5979db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod  for (i = 0; i < len; i++)
5989db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod    if (positions[i].back)
5999db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      {
6009db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	unsigned int back = i - positions[i].back;
6019db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	positions[i].back = 0;
6029db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	positions[i].x_offset += positions[back].x_offset;
6039db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	positions[i].y_offset += positions[back].y_offset;
6049db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod
6059db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	if (buffer->direction == HB_DIRECTION_RTL)
6069db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	  for (j = back + 1; j < i + 1; j++) {
6079db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	    positions[i].x_offset += positions[j].x_advance;
6089db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	    positions[i].y_offset += positions[j].y_advance;
6099db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	  }
6109db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	else
6119db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	  for (j = back; j < i; j++) {
6129db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	    positions[i].x_offset -= positions[j].x_advance;
6139db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	    positions[i].y_offset -= positions[j].y_advance;
6149db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod	  }
6159db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod      }
6169db8ad75317d589807e7725455f49cafece58d5dBehdad Esfahbod}
617