blob: 61c56974350afec00d2373d91d6386c1eaaebbd1 [file] [log] [blame]
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
Behdad Esfahbod5b93e8d2012-04-23 22:26:13 -04003 * Copyright © 2010,2012 Google, Inc.
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04004 *
Behdad Esfahbodc755cb32010-04-22 00:11:43 -04005 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04006 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
Behdad Esfahbod98370e82010-10-27 17:39:01 -040026 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040027 */
28
Behdad Esfahbod7a750ac2011-08-17 14:19:59 +020029#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
30#define HB_OT_LAYOUT_GPOS_TABLE_HH
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040031
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -040032#include "hb-ot-layout-gsubgpos-private.hh"
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040033
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040034
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -040035
Behdad Esfahbodb65c0602011-07-28 16:48:43 -040036/* buffer **position** var allocations */
Behdad Esfahbod194d4562010-10-27 23:09:10 -040037#define attach_lookback() var.u16[0] /* number of glyphs to go back to attach this glyph to its base */
38#define cursive_chain() var.i16[1] /* character to which this connects, may be positive or negative */
39
40
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040041/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
42
Behdad Esfahbodc2ddfd22010-05-06 13:06:15 -040043typedef USHORT Value;
Behdad Esfahbodc91facd2009-08-26 18:53:43 -040044
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -040045typedef Value ValueRecord[VAR];
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040046
Behdad Esfahbodfca6a0d2009-05-21 04:49:04 -040047struct ValueFormat : USHORT
48{
Behdad Esfahbodc6035cf2012-04-12 13:23:59 -040049 enum Flags {
Behdad Esfahbodfca6a0d2009-05-21 04:49:04 -040050 xPlacement = 0x0001, /* Includes horizontal adjustment for placement */
51 yPlacement = 0x0002, /* Includes vertical adjustment for placement */
52 xAdvance = 0x0004, /* Includes horizontal adjustment for advance */
53 yAdvance = 0x0008, /* Includes vertical adjustment for advance */
54 xPlaDevice = 0x0010, /* Includes horizontal Device table for placement */
55 yPlaDevice = 0x0020, /* Includes vertical Device table for placement */
56 xAdvDevice = 0x0040, /* Includes horizontal Device table for advance */
57 yAdvDevice = 0x0080, /* Includes vertical Device table for advance */
Behdad Esfahbode4b92b82009-05-26 15:38:53 -040058 ignored = 0x0F00, /* Was used in TrueType Open for MM fonts */
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -040059 reserved = 0xF000, /* For future use */
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -040060
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -040061 devices = 0x00F0 /* Mask for having any Device table */
Behdad Esfahbodfca6a0d2009-05-21 04:49:04 -040062 };
63
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -040064/* All fields are options. Only those available advance the value pointer. */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040065#if 0
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040066 SHORT xPlacement; /* Horizontal adjustment for
67 * placement--in design units */
68 SHORT yPlacement; /* Vertical adjustment for
69 * placement--in design units */
70 SHORT xAdvance; /* Horizontal adjustment for
71 * advance--in design units (only used
72 * for horizontal writing) */
73 SHORT yAdvance; /* Vertical adjustment for advance--in
74 * design units (only used for vertical
75 * writing) */
76 Offset xPlaDevice; /* Offset to Device table for
77 * horizontal placement--measured from
78 * beginning of PosTable (may be NULL) */
79 Offset yPlaDevice; /* Offset to Device table for vertical
80 * placement--measured from beginning
81 * of PosTable (may be NULL) */
82 Offset xAdvDevice; /* Offset to Device table for
83 * horizontal advance--measured from
84 * beginning of PosTable (may be NULL) */
85 Offset yAdvDevice; /* Offset to Device table for vertical
86 * advance--measured from beginning of
87 * PosTable (may be NULL) */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -040088#endif
89
Behdad Esfahbod7f97d2c2010-10-01 18:58:50 -040090 inline unsigned int get_len (void) const
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -040091 { return _hb_popcount32 ((unsigned int) *this); }
Behdad Esfahbod7f97d2c2010-10-01 18:58:50 -040092 inline unsigned int get_size (void) const
Behdad Esfahbode45d3f82010-05-06 19:33:31 -040093 { return get_len () * Value::static_size; }
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -040094
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -040095 void apply_value (hb_font_t *font,
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -040096 hb_direction_t direction,
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -040097 const void *base,
98 const Value *values,
99 hb_glyph_position_t &glyph_pos) const
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400100 {
101 unsigned int x_ppem, y_ppem;
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400102 unsigned int format = *this;
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400103 hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (direction);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400104
105 if (!format) return;
106
Behdad Esfahbodb6f902a2011-05-11 00:04:15 -0400107 if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++));
108 if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++));
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400109 if (format & xAdvance) {
110 if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values++)); else values++;
111 }
Behdad Esfahbodcc2086d2011-05-19 19:19:50 -0400112 /* y_advance values grow downward but font-space grows upward, hence negation */
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400113 if (format & yAdvance) {
114 if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values++)); else values++;
115 }
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400116
Behdad Esfahboda8d960b2010-04-29 14:31:56 -0400117 if (!has_device ()) return;
118
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400119 x_ppem = font->x_ppem;
120 y_ppem = font->y_ppem;
Behdad Esfahboda8d960b2010-04-29 14:31:56 -0400121
122 if (!x_ppem && !y_ppem) return;
123
Behdad Esfahbod0090dc02009-07-30 16:28:45 -0400124 /* pixel -> fractional pixel */
125 if (format & xPlaDevice) {
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400126 if (x_ppem) glyph_pos.x_offset += (base + get_device (values++)).get_x_delta (font); else values++;
Behdad Esfahbod0090dc02009-07-30 16:28:45 -0400127 }
128 if (format & yPlaDevice) {
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400129 if (y_ppem) glyph_pos.y_offset += (base + get_device (values++)).get_y_delta (font); else values++;
Behdad Esfahbod0090dc02009-07-30 16:28:45 -0400130 }
131 if (format & xAdvDevice) {
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400132 if (horizontal && x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++;
Behdad Esfahbod0090dc02009-07-30 16:28:45 -0400133 }
134 if (format & yAdvDevice) {
Behdad Esfahbodcc2086d2011-05-19 19:19:50 -0400135 /* y_advance values grow downward but font-space grows upward, hence negation */
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400136 if (!horizontal && y_ppem) glyph_pos.y_advance -= (base + get_device (values++)).get_y_delta (font); else values++;
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400137 }
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400138 }
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400139
140 private:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400141 inline bool sanitize_value_devices (hb_sanitize_context_t *c, void *base, Value *values) {
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400142 unsigned int format = *this;
143
144 if (format & xPlacement) values++;
145 if (format & yPlacement) values++;
146 if (format & xAdvance) values++;
147 if (format & yAdvance) values++;
148
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400149 if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
150 if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
151 if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
152 if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400153
154 return true;
155 }
156
Behdad Esfahbodc2ddfd22010-05-06 13:06:15 -0400157 static inline OffsetTo<Device>& get_device (Value* value)
158 { return *CastP<OffsetTo<Device> > (value); }
159 static inline const OffsetTo<Device>& get_device (const Value* value)
160 { return *CastP<OffsetTo<Device> > (value); }
161
162 static inline const SHORT& get_short (const Value* value)
163 { return *CastP<SHORT> (value); }
164
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400165 public:
166
Behdad Esfahbod7f97d2c2010-10-01 18:58:50 -0400167 inline bool has_device (void) const {
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400168 unsigned int format = *this;
169 return (format & devices) != 0;
170 }
171
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400172 inline bool sanitize_value (hb_sanitize_context_t *c, void *base, Value *values) {
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400173 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200174 return TRACE_RETURN (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400175 }
176
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400177 inline bool sanitize_values (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count) {
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400178 TRACE_SANITIZE ();
179 unsigned int len = get_len ();
180
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200181 if (!c->check_array (values, get_size (), count)) return TRACE_RETURN (false);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400182
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200183 if (!has_device ()) return TRACE_RETURN (true);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400184
185 for (unsigned int i = 0; i < count; i++) {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400186 if (!sanitize_value_devices (c, base, values))
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200187 return TRACE_RETURN (false);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400188 values += len;
189 }
190
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200191 return TRACE_RETURN (true);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400192 }
193
Behdad Esfahbod278a91f2010-04-22 13:59:39 -0400194 /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400195 inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, void *base, Value *values, unsigned int count, unsigned int stride) {
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400196 TRACE_SANITIZE ();
197
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200198 if (!has_device ()) return TRACE_RETURN (true);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400199
200 for (unsigned int i = 0; i < count; i++) {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400201 if (!sanitize_value_devices (c, base, values))
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200202 return TRACE_RETURN (false);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400203 values += stride;
204 }
205
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200206 return TRACE_RETURN (true);
Behdad Esfahbod673a4ef2010-04-21 02:02:57 -0400207 }
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400208};
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400209
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400210
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400211struct AnchorFormat1
212{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400213 friend struct Anchor;
214
215 private:
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400216 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400217 hb_position_t *x, hb_position_t *y) const
218 {
Behdad Esfahbodb6f902a2011-05-11 00:04:15 -0400219 *x = font->em_scale_x (xCoordinate);
220 *y = font->em_scale_y (yCoordinate);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400221 }
222
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400223 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400224 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200225 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400226 }
227
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400228 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400229 USHORT format; /* Format identifier--format = 1 */
230 SHORT xCoordinate; /* Horizontal value--in design units */
231 SHORT yCoordinate; /* Vertical value--in design units */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400232 public:
233 DEFINE_SIZE_STATIC (6);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400234};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400235
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400236struct AnchorFormat2
237{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400238 friend struct Anchor;
239
240 private:
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400241 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400242 hb_position_t *x, hb_position_t *y) const
243 {
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400244 unsigned int x_ppem = font->x_ppem;
245 unsigned int y_ppem = font->y_ppem;
Behdad Esfahbod6f729b42010-04-29 03:59:06 -0400246 hb_position_t cx, cy;
Behdad Esfahbod03420342010-11-03 15:40:07 -0400247 hb_bool_t ret = false;
Behdad Esfahbod6f729b42010-04-29 03:59:06 -0400248
249 if (x_ppem || y_ppem)
Behdad Esfahbod60fbb362011-05-19 18:46:15 -0400250 ret = hb_font_get_glyph_contour_point_for_origin (font, glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
Behdad Esfahbodb6f902a2011-05-11 00:04:15 -0400251 *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
252 *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400253 }
254
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400255 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400256 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200257 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400258 }
259
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400260 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400261 USHORT format; /* Format identifier--format = 2 */
262 SHORT xCoordinate; /* Horizontal value--in design units */
263 SHORT yCoordinate; /* Vertical value--in design units */
264 USHORT anchorPoint; /* Index to glyph contour point */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400265 public:
266 DEFINE_SIZE_STATIC (8);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400267};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400268
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400269struct AnchorFormat3
270{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400271 friend struct Anchor;
272
273 private:
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400274 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400275 hb_position_t *x, hb_position_t *y) const
276 {
Behdad Esfahbodb6f902a2011-05-11 00:04:15 -0400277 *x = font->em_scale_x (xCoordinate);
278 *y = font->em_scale_y (yCoordinate);
Behdad Esfahbodc18ec2b2009-05-21 04:54:01 -0400279
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400280 if (font->x_ppem)
281 *x += (this+xDeviceTable).get_x_delta (font);
282 if (font->y_ppem)
283 *y += (this+yDeviceTable).get_x_delta (font);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400284 }
285
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400286 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400287 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200288 return TRACE_RETURN (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400289 }
290
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400291 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400292 USHORT format; /* Format identifier--format = 3 */
293 SHORT xCoordinate; /* Horizontal value--in design units */
294 SHORT yCoordinate; /* Vertical value--in design units */
295 OffsetTo<Device>
296 xDeviceTable; /* Offset to Device table for X
297 * coordinate-- from beginning of
298 * Anchor table (may be NULL) */
299 OffsetTo<Device>
300 yDeviceTable; /* Offset to Device table for Y
301 * coordinate-- from beginning of
302 * Anchor table (may be NULL) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400303 public:
304 DEFINE_SIZE_STATIC (10);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400305};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400306
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400307struct Anchor
308{
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400309 inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400310 hb_position_t *x, hb_position_t *y) const
311 {
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400312 *x = *y = 0;
313 switch (u.format) {
Behdad Esfahbod60fbb362011-05-19 18:46:15 -0400314 case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
315 case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
316 case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
317 default: return;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400318 }
319 }
320
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400321 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400322 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200323 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400324 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200325 case 1: return TRACE_RETURN (u.format1.sanitize (c));
326 case 2: return TRACE_RETURN (u.format2.sanitize (c));
327 case 3: return TRACE_RETURN (u.format3.sanitize (c));
328 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400329 }
330 }
331
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400332 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400333 union {
334 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400335 AnchorFormat1 format1;
336 AnchorFormat2 format2;
337 AnchorFormat3 format3;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400338 } u;
Behdad Esfahboded074222010-05-10 18:08:46 -0400339 public:
Behdad Esfahbod596e4712010-05-10 18:47:48 -0400340 DEFINE_SIZE_UNION (2, format);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400341};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400342
343
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400344struct AnchorMatrix
345{
346 inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols) const {
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400347 if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400348 return this+matrix[row * cols + col];
349 }
350
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400351 inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400352 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200353 if (!c->check_struct (this)) return TRACE_RETURN (false);
354 if (unlikely (rows > 0 && cols >= ((unsigned int) -1) / rows)) return TRACE_RETURN (false);
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400355 unsigned int count = rows * cols;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200356 if (!c->check_array (matrix, matrix[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400357 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200358 if (!matrix[i].sanitize (c, this)) return TRACE_RETURN (false);
359 return TRACE_RETURN (true);
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400360 }
361
362 USHORT rows; /* Number of rows */
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400363 protected:
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400364 OffsetTo<Anchor>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500365 matrix[VAR]; /* Matrix of offsets to Anchor tables--
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400366 * from beginning of AnchorMatrix table */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400367 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400368 DEFINE_SIZE_ARRAY (2, matrix);
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400369};
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400370
371
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400372struct MarkRecord
373{
Behdad Esfahbod377bfc52009-05-21 04:58:24 -0400374 friend struct MarkArray;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400375
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400376 inline bool sanitize (hb_sanitize_context_t *c, void *base) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400377 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200378 return TRACE_RETURN (c->check_struct (this) && markAnchor.sanitize (c, base));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400379 }
380
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400381 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400382 USHORT klass; /* Class defined for this mark */
383 OffsetTo<Anchor>
384 markAnchor; /* Offset to Anchor table--from
385 * beginning of MarkArray table */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400386 public:
387 DEFINE_SIZE_STATIC (4);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400388};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400389
Behdad Esfahbodbea34c72010-05-10 17:28:16 -0400390struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage order */
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400391{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400392 inline bool apply (hb_apply_context_t *c,
Behdad Esfahbodb41f2102009-08-14 19:33:24 -0400393 unsigned int mark_index, unsigned int glyph_index,
394 const AnchorMatrix &anchors, unsigned int class_count,
395 unsigned int glyph_pos) const
396 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400397 TRACE_APPLY ();
Behdad Esfahbodbea34c72010-05-10 17:28:16 -0400398 const MarkRecord &record = ArrayOf<MarkRecord>::operator[](mark_index);
Behdad Esfahbodb41f2102009-08-14 19:33:24 -0400399 unsigned int mark_class = record.klass;
400
401 const Anchor& mark_anchor = this + record.markAnchor;
402 const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count);
403
404 hb_position_t mark_x, mark_y, base_x, base_y;
405
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200406 mark_anchor.get_anchor (c->font, c->buffer->cur().codepoint, &mark_x, &mark_y);
Behdad Esfahbod60fbb362011-05-19 18:46:15 -0400407 glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
Behdad Esfahbodb41f2102009-08-14 19:33:24 -0400408
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200409 hb_glyph_position_t &o = c->buffer->cur_pos();
Behdad Esfahbod194d4562010-10-27 23:09:10 -0400410 o.x_offset = base_x - mark_x;
411 o.y_offset = base_y - mark_y;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400412 o.attach_lookback() = c->buffer->idx - glyph_pos;
Behdad Esfahbodb41f2102009-08-14 19:33:24 -0400413
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400414 c->buffer->idx++;
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200415 return TRACE_RETURN (true);
Behdad Esfahbodb41f2102009-08-14 19:33:24 -0400416 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400417
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400418 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400419 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200420 return TRACE_RETURN (ArrayOf<MarkRecord>::sanitize (c, this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400421 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400422};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400423
424
425/* Lookups */
426
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400427struct SinglePosFormat1
428{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400429 friend struct SinglePos;
430
431 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400432
433 inline const Coverage &get_coverage (void) const
434 {
435 return this+coverage;
436 }
437
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400438 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400439 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400440 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200441 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200442 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400443
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400444 valueFormat.apply_value (c->font, c->direction, this,
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200445 values, c->buffer->cur_pos());
Behdad Esfahbodf53d4342009-05-30 22:17:32 -0400446
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400447 c->buffer->idx++;
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200448 return TRACE_RETURN (true);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400449 }
450
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400451 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400452 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200453 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_value (c, this, values));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400454 }
455
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400456 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400457 USHORT format; /* Format identifier--format = 1 */
458 OffsetTo<Coverage>
459 coverage; /* Offset to Coverage table--from
460 * beginning of subtable */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400461 ValueFormat valueFormat; /* Defines the types of data in the
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400462 * ValueRecord */
463 ValueRecord values; /* Defines positioning
464 * value(s)--applied to all glyphs in
465 * the Coverage table */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400466 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400467 DEFINE_SIZE_ARRAY (6, values);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400468};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400469
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400470struct SinglePosFormat2
471{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400472 friend struct SinglePos;
473
474 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400475
476 inline const Coverage &get_coverage (void) const
477 {
478 return this+coverage;
479 }
480
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400481 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400482 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400483 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200484 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200485 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400486
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200487 if (likely (index >= valueCount)) return TRACE_RETURN (false);
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400488
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400489 valueFormat.apply_value (c->font, c->direction, this,
Behdad Esfahbod4b8487d2010-03-16 03:46:17 -0400490 &values[index * valueFormat.get_len ()],
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200491 c->buffer->cur_pos());
Behdad Esfahbodf53d4342009-05-30 22:17:32 -0400492
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400493 c->buffer->idx++;
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200494 return TRACE_RETURN (true);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400495 }
496
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400497 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400498 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200499 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && valueFormat.sanitize_values (c, this, values, valueCount));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400500 }
501
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400502 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400503 USHORT format; /* Format identifier--format = 2 */
504 OffsetTo<Coverage>
505 coverage; /* Offset to Coverage table--from
506 * beginning of subtable */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400507 ValueFormat valueFormat; /* Defines the types of data in the
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400508 * ValueRecord */
509 USHORT valueCount; /* Number of ValueRecords */
510 ValueRecord values; /* Array of ValueRecords--positioning
511 * values applied to glyphs */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400512 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400513 DEFINE_SIZE_ARRAY (8, values);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400514};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400515
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400516struct SinglePos
517{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400518 friend struct PosLookupSubTable;
519
520 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400521
522 inline const Coverage &get_coverage (void) const
523 {
524 switch (u.format) {
525 case 1: return u.format1.get_coverage ();
526 case 2: return u.format2.get_coverage ();
527 default:return Null(Coverage);
528 }
529 }
530
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400531 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400532 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400533 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400534 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200535 case 1: return TRACE_RETURN (u.format1.apply (c));
536 case 2: return TRACE_RETURN (u.format2.apply (c));
537 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400538 }
539 }
540
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400541 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400542 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200543 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400544 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200545 case 1: return TRACE_RETURN (u.format1.sanitize (c));
546 case 2: return TRACE_RETURN (u.format2.sanitize (c));
547 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400548 }
549 }
550
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400551 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400552 union {
553 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400554 SinglePosFormat1 format1;
555 SinglePosFormat2 format2;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400556 } u;
557};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400558
559
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400560struct PairValueRecord
561{
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400562 friend struct PairSet;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400563
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400564 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400565 GlyphID secondGlyph; /* GlyphID of second glyph in the
566 * pair--first glyph is listed in the
567 * Coverage table */
568 ValueRecord values; /* Positioning data for the first glyph
569 * followed by for second glyph */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400570 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400571 DEFINE_SIZE_ARRAY (2, values);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400572};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400573
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400574struct PairSet
575{
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400576 friend struct PairPosFormat1;
577
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400578 inline bool apply (hb_apply_context_t *c,
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400579 const ValueFormat *valueFormats,
580 unsigned int pos) const
581 {
582 TRACE_APPLY ();
583 unsigned int len1 = valueFormats[0].get_len ();
584 unsigned int len2 = valueFormats[1].get_len ();
585 unsigned int record_size = USHORT::static_size * (1 + len1 + len2);
586
587 unsigned int count = len;
588 const PairValueRecord *record = CastP<PairValueRecord> (array);
589 for (unsigned int i = 0; i < count; i++)
590 {
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -0400591 if (c->buffer->info[pos].codepoint == record->secondGlyph)
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400592 {
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400593 valueFormats[0].apply_value (c->font, c->direction, this,
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200594 &record->values[0], c->buffer->cur_pos());
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400595 valueFormats[1].apply_value (c->font, c->direction, this,
596 &record->values[len1], c->buffer->pos[pos]);
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400597 if (len2)
598 pos++;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400599 c->buffer->idx = pos;
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200600 return TRACE_RETURN (true);
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400601 }
602 record = &StructAtOffset<PairValueRecord> (record, record_size);
603 }
604
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200605 return TRACE_RETURN (false);
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400606 }
607
608 struct sanitize_closure_t {
609 void *base;
610 ValueFormat *valueFormats;
611 unsigned int len1; /* valueFormats[0].get_len() */
612 unsigned int stride; /* 1 + len1 + len2 */
613 };
614
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400615 inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400616 TRACE_SANITIZE ();
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400617 if (!(c->check_struct (this)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200618 && c->check_array (array, USHORT::static_size * closure->stride, len))) return TRACE_RETURN (false);
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400619
620 unsigned int count = len;
621 PairValueRecord *record = CastP<PairValueRecord> (array);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200622 return TRACE_RETURN (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride)
623 && closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400624 }
625
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400626 protected:
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400627 USHORT len; /* Number of PairValueRecords */
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400628 USHORT array[VAR]; /* Array of PairValueRecords--ordered
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400629 * by GlyphID of the second glyph */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400630 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400631 DEFINE_SIZE_ARRAY (2, array);
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400632};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400633
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400634struct PairPosFormat1
635{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400636 friend struct PairPos;
637
638 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400639
640 inline const Coverage &get_coverage (void) const
641 {
642 return this+coverage;
643 }
644
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400645 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400646 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400647 TRACE_APPLY ();
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500648 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200649 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400650
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200651 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200652 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400653
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200654 if (!skippy_iter.next ()) return TRACE_RETURN (false);
Behdad Esfahbodb24ecba2009-05-19 22:16:04 -0400655
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200656 return TRACE_RETURN ((this+pairSet[index]).apply (c, &valueFormat1, skippy_iter.idx));
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400657 }
658
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400659 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400660 TRACE_SANITIZE ();
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -0400661
662 unsigned int len1 = valueFormat1.get_len ();
663 unsigned int len2 = valueFormat2.get_len ();
Behdad Esfahbod70c9bfd2010-05-11 00:23:50 -0400664 PairSet::sanitize_closure_t closure = {
665 this,
666 &valueFormat1,
667 len1,
668 1 + len1 + len2
669 };
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -0400670
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200671 return TRACE_RETURN (c->check_struct (this) && coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400672 }
673
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400674 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400675 USHORT format; /* Format identifier--format = 1 */
676 OffsetTo<Coverage>
677 coverage; /* Offset to Coverage table--from
678 * beginning of subtable */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400679 ValueFormat valueFormat1; /* Defines the types of data in
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400680 * ValueRecord1--for the first glyph
681 * in the pair--may be zero (0) */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400682 ValueFormat valueFormat2; /* Defines the types of data in
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400683 * ValueRecord2--for the second glyph
684 * in the pair--may be zero (0) */
685 OffsetArrayOf<PairSet>
686 pairSet; /* Array of PairSet tables
687 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400688 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400689 DEFINE_SIZE_ARRAY (10, pairSet);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400690};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400691
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400692struct PairPosFormat2
693{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400694 friend struct PairPos;
695
696 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400697
698 inline const Coverage &get_coverage (void) const
699 {
700 return this+coverage;
701 }
702
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400703 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400704 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400705 TRACE_APPLY ();
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500706 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200707 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400708
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200709 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200710 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400711
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200712 if (!skippy_iter.next ()) return TRACE_RETURN (false);
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400713
714 unsigned int len1 = valueFormat1.get_len ();
715 unsigned int len2 = valueFormat2.get_len ();
716 unsigned int record_len = len1 + len2;
717
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200718 unsigned int klass1 = (this+classDef1) (c->buffer->cur().codepoint);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500719 unsigned int klass2 = (this+classDef2) (c->buffer->info[skippy_iter.idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200720 if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return TRACE_RETURN (false);
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400721
Behdad Esfahbod4b8487d2010-03-16 03:46:17 -0400722 const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400723 valueFormat1.apply_value (c->font, c->direction, this,
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200724 v, c->buffer->cur_pos());
Behdad Esfahbod3b0bb852011-05-20 15:59:59 -0400725 valueFormat2.apply_value (c->font, c->direction, this,
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500726 v + len1, c->buffer->pos[skippy_iter.idx]);
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400727
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500728 c->buffer->idx = skippy_iter.idx;
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400729 if (len2)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500730 c->buffer->idx++;
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400731
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200732 return TRACE_RETURN (true);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400733 }
734
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400735 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400736 TRACE_SANITIZE ();
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400737 if (!(c->check_struct (this)
738 && coverage.sanitize (c, this)
739 && classDef1.sanitize (c, this)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200740 && classDef2.sanitize (c, this))) return TRACE_RETURN (false);
Behdad Esfahbod815a73e2009-08-14 17:31:16 -0400741
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -0400742 unsigned int len1 = valueFormat1.get_len ();
743 unsigned int len2 = valueFormat2.get_len ();
744 unsigned int stride = len1 + len2;
Behdad Esfahbod4b8487d2010-03-16 03:46:17 -0400745 unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
Behdad Esfahbodeba8b4f2010-03-29 00:04:12 -0400746 unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200747 return TRACE_RETURN (c->check_array (values, record_size, count) &&
748 valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
749 valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400750 }
Behdad Esfahbod70632ad2009-05-19 22:30:09 -0400751
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400752 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400753 USHORT format; /* Format identifier--format = 2 */
754 OffsetTo<Coverage>
755 coverage; /* Offset to Coverage table--from
756 * beginning of subtable */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400757 ValueFormat valueFormat1; /* ValueRecord definition--for the
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400758 * first glyph of the pair--may be zero
759 * (0) */
Behdad Esfahbod056c7ec2009-05-18 19:47:52 -0400760 ValueFormat valueFormat2; /* ValueRecord definition--for the
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400761 * second glyph of the pair--may be
762 * zero (0) */
763 OffsetTo<ClassDef>
764 classDef1; /* Offset to ClassDef table--from
765 * beginning of PairPos subtable--for
766 * the first glyph of the pair */
767 OffsetTo<ClassDef>
768 classDef2; /* Offset to ClassDef table--from
769 * beginning of PairPos subtable--for
770 * the second glyph of the pair */
771 USHORT class1Count; /* Number of classes in ClassDef1
772 * table--includes Class0 */
773 USHORT class2Count; /* Number of classes in ClassDef2
774 * table--includes Class0 */
775 ValueRecord values; /* Matrix of value pairs:
776 * class1-major, class2-minor,
777 * Each entry has value1 and value2 */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400778 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400779 DEFINE_SIZE_ARRAY (16, values);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400780};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400781
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400782struct PairPos
783{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400784 friend struct PosLookupSubTable;
785
786 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400787
788 inline const Coverage &get_coverage (void) const
789 {
790 switch (u.format) {
791 case 1: return u.format1.get_coverage ();
792 case 2: return u.format2.get_coverage ();
793 default:return Null(Coverage);
794 }
795 }
796
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400797 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400798 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400799 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400800 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200801 case 1: return TRACE_RETURN (u.format1.apply (c));
802 case 2: return TRACE_RETURN (u.format2.apply (c));
803 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400804 }
805 }
806
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400807 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400808 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200809 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400810 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200811 case 1: return TRACE_RETURN (u.format1.sanitize (c));
812 case 2: return TRACE_RETURN (u.format2.sanitize (c));
813 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400814 }
815 }
816
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400817 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400818 union {
819 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400820 PairPosFormat1 format1;
821 PairPosFormat2 format2;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400822 } u;
823};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400824
825
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400826struct EntryExitRecord
827{
Behdad Esfahbod569da922010-05-10 16:38:32 -0400828 friend struct CursivePosFormat1;
829
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400830 inline bool sanitize (hb_sanitize_context_t *c, void *base) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400831 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200832 return TRACE_RETURN (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400833 }
834
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400835 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400836 OffsetTo<Anchor>
837 entryAnchor; /* Offset to EntryAnchor table--from
838 * beginning of CursivePos
839 * subtable--may be NULL */
840 OffsetTo<Anchor>
841 exitAnchor; /* Offset to ExitAnchor table--from
842 * beginning of CursivePos
843 * subtable--may be NULL */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400844 public:
845 DEFINE_SIZE_STATIC (4);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400846};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400847
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400848struct CursivePosFormat1
849{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400850 friend struct CursivePos;
851
852 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400853
854 inline const Coverage &get_coverage (void) const
855 {
856 return this+coverage;
857 }
858
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400859 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbodd18fd8e2009-05-19 23:25:41 -0400860 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400861 TRACE_APPLY ();
Behdad Esfahbod0f7e6b22009-05-20 04:16:35 -0400862
863 /* We don't handle mark glyphs here. */
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200864 if (c->property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) return TRACE_RETURN (false);
Behdad Esfahbod0f7e6b22009-05-20 04:16:35 -0400865
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500866 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200867 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
Behdad Esfahbod0f7e6b22009-05-20 04:16:35 -0400868
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200869 const EntryExitRecord &this_record = entryExitRecord[(this+coverage) (c->buffer->cur().codepoint)];
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200870 if (!this_record.exitAnchor) return TRACE_RETURN (false);
Behdad Esfahbodd18fd8e2009-05-19 23:25:41 -0400871
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200872 if (!skippy_iter.next ()) return TRACE_RETURN (false);
Behdad Esfahbodd18fd8e2009-05-19 23:25:41 -0400873
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500874 const EntryExitRecord &next_record = entryExitRecord[(this+coverage) (c->buffer->info[skippy_iter.idx].codepoint)];
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200875 if (!next_record.entryAnchor) return TRACE_RETURN (false);
Behdad Esfahbodaf5d02a2010-10-27 11:54:26 -0400876
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400877 unsigned int i = c->buffer->idx;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500878 unsigned int j = skippy_iter.idx;
Behdad Esfahbodaf5d02a2010-10-27 11:54:26 -0400879
880 hb_position_t entry_x, entry_y, exit_x, exit_y;
Behdad Esfahbod60fbb362011-05-19 18:46:15 -0400881 (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y);
882 (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y);
Behdad Esfahbodcc83ae12009-05-27 00:17:37 -0400883
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400884 hb_glyph_position_t *pos = c->buffer->pos;
885
886 hb_position_t d;
887 /* Main-direction adjustment */
888 switch (c->direction) {
889 case HB_DIRECTION_LTR:
890 pos[i].x_advance = exit_x + pos[i].x_offset;
891
892 d = entry_x + pos[j].x_offset;
893 pos[j].x_advance -= d;
894 pos[j].x_offset -= d;
895 break;
896 case HB_DIRECTION_RTL:
897 d = exit_x + pos[i].x_offset;
898 pos[i].x_advance -= d;
899 pos[i].x_offset -= d;
900
901 pos[j].x_advance = entry_x + pos[j].x_offset;
902 break;
903 case HB_DIRECTION_TTB:
904 pos[i].y_advance = exit_y + pos[i].y_offset;
905
906 d = entry_y + pos[j].y_offset;
907 pos[j].y_advance -= d;
908 pos[j].y_offset -= d;
909 break;
910 case HB_DIRECTION_BTT:
911 d = exit_y + pos[i].y_offset;
912 pos[i].y_advance -= d;
913 pos[i].y_offset -= d;
914
915 pos[j].y_advance = entry_y;
916 break;
917 case HB_DIRECTION_INVALID:
918 default:
919 break;
Behdad Esfahbodd18fd8e2009-05-19 23:25:41 -0400920 }
921
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400922 /* Cross-direction adjustment */
923 if (c->lookup_props & LookupFlag::RightToLeft) {
924 pos[i].cursive_chain() = j - i;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400925 if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400926 pos[i].y_offset = entry_y - exit_y;
Behdad Esfahbod13528d02010-10-27 14:09:27 -0400927 else
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400928 pos[i].x_offset = entry_x - exit_x;
929 } else {
930 pos[j].cursive_chain() = i - j;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400931 if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400932 pos[j].y_offset = exit_y - entry_y;
Behdad Esfahbod13528d02010-10-27 14:09:27 -0400933 else
Behdad Esfahbod7403e052011-05-24 21:04:15 -0400934 pos[j].x_offset = exit_x - entry_x;
Behdad Esfahbodd18fd8e2009-05-19 23:25:41 -0400935 }
936
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400937 c->buffer->idx = j;
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200938 return TRACE_RETURN (true);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400939 }
940
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400941 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400942 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200943 return TRACE_RETURN (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400944 }
945
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400946 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400947 USHORT format; /* Format identifier--format = 1 */
948 OffsetTo<Coverage>
949 coverage; /* Offset to Coverage table--from
950 * beginning of subtable */
951 ArrayOf<EntryExitRecord>
952 entryExitRecord; /* Array of EntryExit records--in
953 * Coverage Index order */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400954 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400955 DEFINE_SIZE_ARRAY (6, entryExitRecord);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400956};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400957
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400958struct CursivePos
959{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400960 friend struct PosLookupSubTable;
961
962 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400963
964 inline const Coverage &get_coverage (void) const
965 {
966 switch (u.format) {
967 case 1: return u.format1.get_coverage ();
968 default:return Null(Coverage);
969 }
970 }
971
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400972 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -0400973 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400974 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400975 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200976 case 1: return TRACE_RETURN (u.format1.apply (c));
977 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400978 }
979 }
980
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400981 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400982 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200983 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400984 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200985 case 1: return TRACE_RETURN (u.format1.sanitize (c));
986 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -0400987 }
988 }
989
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400990 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400991 union {
992 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400993 CursivePosFormat1 format1;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400994 } u;
995};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -0400996
997
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -0400998typedef AnchorMatrix BaseArray; /* base-major--
999 * in order of BaseCoverage Index--,
1000 * mark-minor--
Behdad Esfahbodfb3b5cc2009-05-21 04:47:05 -04001001 * ordered by class--zero-based. */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001002
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001003struct MarkBasePosFormat1
1004{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001005 friend struct MarkBasePos;
1006
1007 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001008
1009 inline const Coverage &get_coverage (void) const
1010 {
1011 return this+markCoverage;
1012 }
1013
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001014 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001015 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001016 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001017 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001018 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod357ccde2009-05-21 06:32:01 -04001019
1020 /* now we search backwards for a non-mark glyph */
Behdad Esfahbod1376fb72010-04-29 02:19:21 -04001021 unsigned int property;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001022 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbod7b84c532012-06-08 22:04:23 -04001023 do {
1024 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
1025 /* We only want to attach to the first of a MultipleSubst sequence. Reject others. */
1026 if (0 == get_lig_comp (c->buffer->info[skippy_iter.idx])) break;
1027 skippy_iter.reject ();
1028 } while (1);
Behdad Esfahbod0532ed12009-08-12 15:40:04 -04001029
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001030 /* The following assertion is too strong, so we've disabled it. */
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001031 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH)) {/*return TRACE_RETURN (false);*/}
Behdad Esfahbod357ccde2009-05-21 06:32:01 -04001032
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001033 unsigned int base_index = (this+baseCoverage) (c->buffer->info[skippy_iter.idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001034 if (base_index == NOT_COVERED) return TRACE_RETURN (false);
Behdad Esfahbod357ccde2009-05-21 06:32:01 -04001035
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001036 return TRACE_RETURN ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001037 }
1038
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001039 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001040 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001041 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && baseCoverage.sanitize (c, this) &&
1042 markArray.sanitize (c, this) && baseArray.sanitize (c, this, (unsigned int) classCount));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001043 }
1044
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001045 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001046 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbodfb3b5cc2009-05-21 04:47:05 -04001047 OffsetTo<Coverage>
1048 markCoverage; /* Offset to MarkCoverage table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001049 * beginning of MarkBasePos subtable */
Behdad Esfahbodfb3b5cc2009-05-21 04:47:05 -04001050 OffsetTo<Coverage>
1051 baseCoverage; /* Offset to BaseCoverage table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001052 * beginning of MarkBasePos subtable */
1053 USHORT classCount; /* Number of classes defined for marks */
Behdad Esfahbodfb3b5cc2009-05-21 04:47:05 -04001054 OffsetTo<MarkArray>
1055 markArray; /* Offset to MarkArray table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001056 * beginning of MarkBasePos subtable */
Behdad Esfahbodfb3b5cc2009-05-21 04:47:05 -04001057 OffsetTo<BaseArray>
1058 baseArray; /* Offset to BaseArray table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001059 * beginning of MarkBasePos subtable */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001060 public:
1061 DEFINE_SIZE_STATIC (12);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001062};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001063
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001064struct MarkBasePos
1065{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001066 friend struct PosLookupSubTable;
1067
1068 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001069
1070 inline const Coverage &get_coverage (void) const
1071 {
1072 switch (u.format) {
1073 case 1: return u.format1.get_coverage ();
1074 default:return Null(Coverage);
1075 }
1076 }
1077
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001078 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001079 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001080 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001081 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001082 case 1: return TRACE_RETURN (u.format1.apply (c));
1083 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001084 }
1085 }
1086
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001087 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001088 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001089 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001090 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001091 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1092 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001093 }
1094 }
1095
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001096 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001097 union {
1098 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001099 MarkBasePosFormat1 format1;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001100 } u;
1101};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001102
1103
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -04001104typedef AnchorMatrix LigatureAttach; /* component-major--
1105 * in order of writing direction--,
1106 * mark-minor--
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001107 * ordered by class--zero-based. */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001108
Behdad Esfahbod3564ee52009-08-14 18:32:56 -04001109typedef OffsetListOf<LigatureAttach> LigatureArray;
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001110 /* Array of LigatureAttach
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001111 * tables ordered by
1112 * LigatureCoverage Index */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001113
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001114struct MarkLigPosFormat1
1115{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001116 friend struct MarkLigPos;
1117
1118 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001119
1120 inline const Coverage &get_coverage (void) const
1121 {
1122 return this+markCoverage;
1123 }
1124
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001125 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001126 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001127 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001128 unsigned int mark_index = (this+markCoverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001129 if (likely (mark_index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001130
1131 /* now we search backwards for a non-mark glyph */
Behdad Esfahbod1376fb72010-04-29 02:19:21 -04001132 unsigned int property;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001133 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001134 if (!skippy_iter.prev (&property, LookupFlag::IgnoreMarks)) return TRACE_RETURN (false);
Behdad Esfahbod0532ed12009-08-12 15:40:04 -04001135
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001136 /* The following assertion is too strong, so we've disabled it. */
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001137 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE)) {/*return TRACE_RETURN (false);*/}
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001138
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001139 unsigned int j = skippy_iter.idx;
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -04001140 unsigned int lig_index = (this+ligatureCoverage) (c->buffer->info[j].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001141 if (lig_index == NOT_COVERED) return TRACE_RETURN (false);
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001142
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001143 const LigatureArray& lig_array = this+ligatureArray;
Behdad Esfahbod3564ee52009-08-14 18:32:56 -04001144 const LigatureAttach& lig_attach = lig_array[lig_index];
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -04001145
1146 /* Find component to attach to */
Behdad Esfahbodb2b18ef2009-08-14 19:37:18 -04001147 unsigned int comp_count = lig_attach.rows;
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001148 if (unlikely (!comp_count)) return TRACE_RETURN (false);
1149
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001150 /* We must now check whether the ligature ID of the current mark glyph
1151 * is identical to the ligature ID of the found ligature. If yes, we
1152 * can directly use the component index. If not, we attach the mark
1153 * glyph to the last component of the ligature. */
Behdad Esfahbod0aef4252012-07-30 00:55:15 -04001154 unsigned int comp_index;
1155 unsigned int lig_id = get_lig_id (c->buffer->info[j]);
1156 unsigned int mark_id = get_lig_id (c->buffer->cur());
1157 unsigned int mark_comp = get_lig_comp (c->buffer->cur());
1158 if (lig_id && lig_id == mark_id && mark_comp > 0)
1159 comp_index = MIN (comp_count, get_lig_comp (c->buffer->cur())) - 1;
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001160 else
Behdad Esfahbodb2b18ef2009-08-14 19:37:18 -04001161 comp_index = comp_count - 1;
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001162
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001163 return TRACE_RETURN ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001164 }
1165
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001166 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001167 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001168 return TRACE_RETURN (c->check_struct (this) && markCoverage.sanitize (c, this) && ligatureCoverage.sanitize (c, this) &&
1169 markArray.sanitize (c, this) && ligatureArray.sanitize (c, this, (unsigned int) classCount));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001170 }
1171
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001172 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001173 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001174 OffsetTo<Coverage>
1175 markCoverage; /* Offset to Mark Coverage table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001176 * beginning of MarkLigPos subtable */
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001177 OffsetTo<Coverage>
1178 ligatureCoverage; /* Offset to Ligature Coverage
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001179 * table--from beginning of MarkLigPos
1180 * subtable */
1181 USHORT classCount; /* Number of defined mark classes */
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001182 OffsetTo<MarkArray>
1183 markArray; /* Offset to MarkArray table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001184 * beginning of MarkLigPos subtable */
Behdad Esfahbod9b006bc2009-05-22 18:29:45 -04001185 OffsetTo<LigatureArray>
1186 ligatureArray; /* Offset to LigatureArray table--from
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001187 * beginning of MarkLigPos subtable */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001188 public:
1189 DEFINE_SIZE_STATIC (12);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001190};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001191
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001192struct MarkLigPos
1193{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001194 friend struct PosLookupSubTable;
1195
1196 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001197
1198 inline const Coverage &get_coverage (void) const
1199 {
1200 switch (u.format) {
1201 case 1: return u.format1.get_coverage ();
1202 default:return Null(Coverage);
1203 }
1204 }
1205
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001206 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001207 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001208 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001209 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001210 case 1: return TRACE_RETURN (u.format1.apply (c));
1211 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001212 }
1213 }
1214
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001215 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001216 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001217 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001218 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001219 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1220 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001221 }
1222 }
1223
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001224 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001225 union {
1226 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001227 MarkLigPosFormat1 format1;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001228 } u;
1229};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001230
1231
Behdad Esfahbodcb71a2f2009-08-14 18:14:03 -04001232typedef AnchorMatrix Mark2Array; /* mark2-major--
1233 * in order of Mark2Coverage Index--,
1234 * mark1-minor--
1235 * ordered by class--zero-based. */
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001236
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001237struct MarkMarkPosFormat1
1238{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001239 friend struct MarkMarkPos;
1240
1241 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001242
1243 inline const Coverage &get_coverage (void) const
1244 {
1245 return this+mark1Coverage;
1246 }
1247
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001248 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001249 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001250 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001251 unsigned int mark1_index = (this+mark1Coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001252 if (likely (mark1_index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001253
1254 /* now we search backwards for a suitable mark glyph until a non-mark glyph */
Behdad Esfahbod1376fb72010-04-29 02:19:21 -04001255 unsigned int property;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001256 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->idx, 1);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001257 if (!skippy_iter.prev (&property)) return TRACE_RETURN (false);
Behdad Esfahbod0532ed12009-08-12 15:40:04 -04001258
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001259 if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) return TRACE_RETURN (false);
Behdad Esfahbod80ea5bd2009-05-26 17:58:37 -04001260
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001261 unsigned int j = skippy_iter.idx;
1262
Behdad Esfahbod5d874d52012-07-28 21:05:25 -04001263 unsigned int id1 = get_lig_id (c->buffer->cur());
1264 unsigned int id2 = get_lig_id (c->buffer->info[j]);
1265 unsigned int comp1 = get_lig_comp (c->buffer->cur());
1266 unsigned int comp2 = get_lig_comp (c->buffer->info[j]);
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001267
Behdad Esfahbod5d874d52012-07-28 21:05:25 -04001268 if (likely (id1 == id2)) {
1269 if (id1 == 0) /* Marks belonging to the same base. */
1270 goto good;
1271 else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
1272 goto good;
1273 } else {
1274 /* If ligature ids don't match, it may be the case that one of the marks
1275 * itself is a ligature. In which case match. */
1276 if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
1277 goto good;
1278 }
1279
1280 /* Didn't match. */
1281 return TRACE_RETURN (false);
1282
1283 good:
Behdad Esfahbod7e7007a2010-05-14 22:02:37 -04001284 unsigned int mark2_index = (this+mark2Coverage) (c->buffer->info[j].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001285 if (mark2_index == NOT_COVERED) return TRACE_RETURN (false);
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001286
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001287 return TRACE_RETURN ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001288 }
1289
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001290 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001291 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001292 return TRACE_RETURN (c->check_struct (this) && mark1Coverage.sanitize (c, this) &&
1293 mark2Coverage.sanitize (c, this) && mark1Array.sanitize (c, this)
1294 && mark2Array.sanitize (c, this, (unsigned int) classCount));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001295 }
1296
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001297 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001298 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001299 OffsetTo<Coverage>
1300 mark1Coverage; /* Offset to Combining Mark1 Coverage
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001301 * table--from beginning of MarkMarkPos
1302 * subtable */
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001303 OffsetTo<Coverage>
1304 mark2Coverage; /* Offset to Combining Mark2 Coverage
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001305 * table--from beginning of MarkMarkPos
1306 * subtable */
Behdad Esfahbodfe550f42009-05-21 08:27:07 -04001307 USHORT classCount; /* Number of defined mark classes */
1308 OffsetTo<MarkArray>
1309 mark1Array; /* Offset to Mark1Array table--from
1310 * beginning of MarkMarkPos subtable */
1311 OffsetTo<Mark2Array>
1312 mark2Array; /* Offset to Mark2Array table--from
1313 * beginning of MarkMarkPos subtable */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001314 public:
1315 DEFINE_SIZE_STATIC (12);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001316};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001317
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001318struct MarkMarkPos
1319{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001320 friend struct PosLookupSubTable;
1321
1322 private:
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001323
1324 inline const Coverage &get_coverage (void) const
1325 {
1326 switch (u.format) {
1327 case 1: return u.format1.get_coverage ();
1328 default:return Null(Coverage);
1329 }
1330 }
1331
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001332 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001333 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001334 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001335 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001336 case 1: return TRACE_RETURN (u.format1.apply (c));
1337 default:return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001338 }
1339 }
1340
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001341 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001342 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001343 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001344 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001345 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1346 default:return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001347 }
1348 }
1349
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001350 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001351 union {
1352 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001353 MarkMarkPosFormat1 format1;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001354 } u;
1355};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001356
1357
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001358static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001359
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001360struct ContextPos : Context
1361{
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001362 friend struct PosLookupSubTable;
1363
1364 private:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001365 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod0535b502009-08-28 17:14:33 -04001366 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001367 TRACE_APPLY ();
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001368 return TRACE_RETURN (Context::apply (c, position_lookup));
Behdad Esfahbod0535b502009-08-28 17:14:33 -04001369 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001370};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001371
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001372struct ChainContextPos : ChainContext
1373{
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001374 friend struct PosLookupSubTable;
1375
1376 private:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001377 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod0535b502009-08-28 17:14:33 -04001378 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001379 TRACE_APPLY ();
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001380 return TRACE_RETURN (ChainContext::apply (c, position_lookup));
Behdad Esfahbod0535b502009-08-28 17:14:33 -04001381 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001382};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001383
1384
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001385struct ExtensionPos : Extension
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001386{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001387 friend struct PosLookupSubTable;
1388
1389 private:
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001390 inline const struct PosLookupSubTable& get_subtable (void) const
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001391 {
1392 unsigned int offset = get_offset ();
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -04001393 if (unlikely (!offset)) return Null(PosLookupSubTable);
Behdad Esfahbod09766b12010-05-10 17:36:03 -04001394 return StructAtOffset<PosLookupSubTable> (this, offset);
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001395 }
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001396
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001397 inline const Coverage &get_coverage (void) const;
1398
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001399 inline bool apply (hb_apply_context_t *c) const;
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001400
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001401 inline bool sanitize (hb_sanitize_context_t *c);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001402};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001403
1404
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001405
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001406/*
1407 * PosLookup
1408 */
1409
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001410
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001411struct PosLookupSubTable
1412{
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001413 friend struct PosLookup;
1414
Behdad Esfahbodc6035cf2012-04-12 13:23:59 -04001415 enum Type {
Behdad Esfahbodff05d252009-05-20 03:53:00 -04001416 Single = 1,
1417 Pair = 2,
1418 Cursive = 3,
1419 MarkBase = 4,
1420 MarkLig = 5,
1421 MarkMark = 6,
1422 Context = 7,
1423 ChainContext = 8,
Behdad Esfahbod8f034d52009-08-18 16:41:59 -04001424 Extension = 9
Behdad Esfahbodff05d252009-05-20 03:53:00 -04001425 };
1426
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001427 inline const Coverage &get_coverage (unsigned int lookup_type) const
Behdad Esfahbodfaf0f202012-06-09 03:02:36 -04001428 {
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001429 switch (lookup_type) {
1430 case Single: return u.single.get_coverage ();
1431 case Pair: return u.pair.get_coverage ();
1432 case Cursive: return u.cursive.get_coverage ();
1433 case MarkBase: return u.markBase.get_coverage ();
1434 case MarkLig: return u.markLig.get_coverage ();
1435 case MarkMark: return u.markMark.get_coverage ();
1436 case Context: return u.context.get_coverage ();
1437 case ChainContext: return u.chainContext.get_coverage ();
1438 case Extension: return u.extension.get_coverage ();
1439 default: return Null(Coverage);
1440 }
Behdad Esfahbodfaf0f202012-06-09 03:02:36 -04001441 }
1442
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001443 inline bool apply (hb_apply_context_t *c, unsigned int lookup_type) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001444 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001445 TRACE_APPLY ();
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001446 switch (lookup_type) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001447 case Single: return TRACE_RETURN (u.single.apply (c));
1448 case Pair: return TRACE_RETURN (u.pair.apply (c));
1449 case Cursive: return TRACE_RETURN (u.cursive.apply (c));
1450 case MarkBase: return TRACE_RETURN (u.markBase.apply (c));
1451 case MarkLig: return TRACE_RETURN (u.markLig.apply (c));
1452 case MarkMark: return TRACE_RETURN (u.markMark.apply (c));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001453 case Context: return TRACE_RETURN (u.context.apply (c));
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001454 case ChainContext: return TRACE_RETURN (u.chainContext.apply (c));
1455 case Extension: return TRACE_RETURN (u.extension.apply (c));
1456 default: return TRACE_RETURN (false);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001457 }
1458 }
1459
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001460 inline bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001461 TRACE_SANITIZE ();
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001462 if (!u.header.sub_format.sanitize (c))
Behdad Esfahbodfaf0f202012-06-09 03:02:36 -04001463 return TRACE_RETURN (false);
Behdad Esfahbodfe9bc072010-05-10 21:39:24 -04001464 switch (lookup_type) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001465 case Single: return TRACE_RETURN (u.single.sanitize (c));
1466 case Pair: return TRACE_RETURN (u.pair.sanitize (c));
1467 case Cursive: return TRACE_RETURN (u.cursive.sanitize (c));
1468 case MarkBase: return TRACE_RETURN (u.markBase.sanitize (c));
1469 case MarkLig: return TRACE_RETURN (u.markLig.sanitize (c));
1470 case MarkMark: return TRACE_RETURN (u.markMark.sanitize (c));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001471 case Context: return TRACE_RETURN (u.context.sanitize (c));
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001472 case ChainContext: return TRACE_RETURN (u.chainContext.sanitize (c));
1473 case Extension: return TRACE_RETURN (u.extension.sanitize (c));
1474 default: return TRACE_RETURN (true);
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001475 }
1476 }
1477
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001478 protected:
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001479 union {
Behdad Esfahbod4e766ff2012-06-09 02:53:57 -04001480 struct {
1481 USHORT sub_format;
Behdad Esfahbod4e766ff2012-06-09 02:53:57 -04001482 } header;
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001483 SinglePos single;
1484 PairPos pair;
1485 CursivePos cursive;
1486 MarkBasePos markBase;
1487 MarkLigPos markLig;
1488 MarkMarkPos markMark;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001489 ContextPos context;
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001490 ChainContextPos chainContext;
1491 ExtensionPos extension;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001492 } u;
Behdad Esfahboded074222010-05-10 18:08:46 -04001493 public:
Behdad Esfahbod4e766ff2012-06-09 02:53:57 -04001494 DEFINE_SIZE_UNION (2, header.sub_format);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001495};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001496
1497
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001498struct PosLookup : Lookup
1499{
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001500 inline const PosLookupSubTable& get_subtable (unsigned int i) const
1501 { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001502
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001503 inline const Coverage *get_coverage (void) const
1504 {
1505 /* Only return non-NULL if there's just one Coverage table we care about. */
1506 const Coverage *c = &get_subtable (0).get_coverage (get_type ());
1507 unsigned int count = get_subtable_count ();
1508 for (unsigned int i = 1; i < count; i++)
1509 if (c != &get_subtable (i).get_coverage (get_type ()))
1510 return NULL;
1511 return c;
1512 }
1513
Behdad Esfahbod41ae6742012-04-11 17:11:05 -04001514 inline bool apply_once (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001515 {
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001516 unsigned int lookup_type = get_type ();
Behdad Esfahbod1376fb72010-04-29 02:19:21 -04001517
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001518 if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->cur(), c->lookup_props, &c->property))
Behdad Esfahbod923923f2009-05-22 17:58:09 -04001519 return false;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001520
Behdad Esfahbod44b8ee02012-06-09 00:23:24 -04001521 unsigned int count = get_subtable_count ();
1522 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001523 if (get_subtable (i).apply (c, lookup_type))
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001524 return true;
1525
1526 return false;
1527 }
1528
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001529 inline bool apply_string (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001530 {
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001531 bool ret = false;
1532
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001533 if (unlikely (!c->buffer->len))
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001534 return false;
1535
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001536 c->set_lookup (*this);
Behdad Esfahbod41ae6742012-04-11 17:11:05 -04001537
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001538 c->buffer->idx = 0;
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001539
1540 /* Fast path for lookups with one coverage only (which is most). */
1541 const Coverage *coverage = get_coverage ();
1542 if (coverage)
1543 while (c->buffer->idx < c->buffer->len)
1544 {
1545 if ((c->buffer->cur().mask & c->lookup_mask) &&
Behdad Esfahboddadede02012-07-28 18:03:20 -04001546 coverage->get_coverage (c->buffer->cur().codepoint) != NOT_COVERED &&
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001547 apply_once (c))
1548 ret = true;
1549 else
1550 c->buffer->idx++;
1551 }
1552 else
1553 while (c->buffer->idx < c->buffer->len)
1554 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -04001555 if ((c->buffer->cur().mask & c->lookup_mask) &&
1556 apply_once (c))
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001557 ret = true;
1558 else
1559 c->buffer->idx++;
1560 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001561
1562 return ret;
1563 }
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001564
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001565 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001566 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001567 if (unlikely (!Lookup::sanitize (c))) return TRACE_RETURN (false);
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001568 OffsetArrayOf<PosLookupSubTable> &list = CastR<OffsetArrayOf<PosLookupSubTable> > (subTable);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001569 return TRACE_RETURN (list.sanitize (c, this, get_type ()));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001570 }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001571};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001572
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001573typedef OffsetListOf<PosLookup> PosLookupList;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001574
1575/*
Behdad Esfahbodae9877d2011-08-17 14:43:45 +02001576 * GPOS -- The Glyph Positioning Table
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001577 */
1578
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001579struct GPOS : GSUBGPOS
1580{
Behdad Esfahboda328d662009-08-04 20:27:05 -04001581 static const hb_tag_t Tag = HB_OT_TAG_GPOS;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001582
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001583 inline const PosLookup& get_lookup (unsigned int i) const
Behdad Esfahbod187454c2010-04-23 16:35:01 -04001584 { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001585
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001586 inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index) const
1587 { return get_lookup (lookup_index).apply_string (c); }
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001588
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -04001589 static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
1590 static inline void position_finish (hb_font_t *font, hb_buffer_t *buffer);
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001591
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001592 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001593 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001594 if (unlikely (!GSUBGPOS::sanitize (c))) return TRACE_RETURN (false);
Behdad Esfahbod187454c2010-04-23 16:35:01 -04001595 OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001596 return TRACE_RETURN (list.sanitize (c, this));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001597 }
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001598 public:
1599 DEFINE_SIZE_STATIC (10);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001600};
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001601
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001602
1603static void
1604fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
1605{
1606 unsigned int j = pos[i].cursive_chain();
1607 if (likely (!j))
1608 return;
1609
1610 j += i;
1611
1612 pos[i].cursive_chain() = 0;
1613
1614 fix_cursive_minor_offset (pos, j, direction);
1615
1616 if (HB_DIRECTION_IS_HORIZONTAL (direction))
1617 pos[i].y_offset += pos[j].y_offset;
1618 else
1619 pos[i].x_offset += pos[j].x_offset;
1620}
1621
1622static void
1623fix_mark_attachment (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
1624{
1625 if (likely (!(pos[i].attach_lookback())))
1626 return;
1627
1628 unsigned int j = i - pos[i].attach_lookback();
1629
Behdad Esfahbod34a74402012-07-20 12:32:59 -04001630// pos[i].x_advance = 0;
1631// pos[i].y_advance = 0;
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001632 pos[i].x_offset += pos[j].x_offset;
1633 pos[i].y_offset += pos[j].y_offset;
1634
1635 if (HB_DIRECTION_IS_FORWARD (direction))
Behdad Esfahbod21deab22011-05-30 11:08:40 -04001636 for (unsigned int k = j; k < i; k++) {
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001637 pos[i].x_offset -= pos[k].x_advance;
1638 pos[i].y_offset -= pos[k].y_advance;
1639 }
1640 else
Behdad Esfahbod21deab22011-05-30 11:08:40 -04001641 for (unsigned int k = j + 1; k < i + 1; k++) {
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001642 pos[i].x_offset += pos[k].x_advance;
1643 pos[i].y_offset += pos[k].y_advance;
1644 }
1645}
1646
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001647void
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -04001648GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
Behdad Esfahboda9ad3d32011-07-28 15:42:18 -04001649{
1650 buffer->clear_positions ();
Behdad Esfahbodb65c0602011-07-28 16:48:43 -04001651
1652 unsigned int count = buffer->len;
1653 for (unsigned int i = 0; i < count; i++)
1654 buffer->pos[i].attach_lookback() = buffer->pos[i].cursive_chain() = 0;
Behdad Esfahboda9ad3d32011-07-28 15:42:18 -04001655}
1656
1657void
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -04001658GPOS::position_finish (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001659{
Ryan Lortie70566be2011-04-15 18:32:36 -04001660 unsigned int len;
1661 hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001662 hb_direction_t direction = buffer->props.direction;
1663
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001664 /* Handle cursive connections */
1665 for (unsigned int i = 0; i < len; i++)
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001666 fix_cursive_minor_offset (pos, i, direction);
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001667
1668 /* Handle attachments */
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001669 for (unsigned int i = 0; i < len; i++)
Behdad Esfahbod7403e052011-05-24 21:04:15 -04001670 fix_mark_attachment (pos, i, direction);
Behdad Esfahbodb65c0602011-07-28 16:48:43 -04001671
Behdad Esfahbodcee71872012-05-11 11:41:39 +02001672 HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
Behdad Esfahboda9844d42012-05-09 17:53:13 +02001673 HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
Behdad Esfahbodb65c0602011-07-28 16:48:43 -04001674 HB_BUFFER_DEALLOCATE_VAR (buffer, props_cache);
Behdad Esfahbod1e7c1fc2010-10-27 22:48:31 -04001675}
1676
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001677
1678/* Out-of-class implementation for methods recursing */
1679
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001680inline const Coverage & ExtensionPos::get_coverage (void) const
1681{
1682 return get_subtable ().get_coverage (get_type ());
1683}
1684
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001685inline bool ExtensionPos::apply (hb_apply_context_t *c) const
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001686{
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001687 TRACE_APPLY ();
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001688 return TRACE_RETURN (get_subtable ().apply (c, get_type ()));
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001689}
1690
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001691inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c)
Behdad Esfahbod42b778f2009-08-04 13:30:49 -04001692{
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001693 TRACE_SANITIZE ();
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001694 if (unlikely (!Extension::sanitize (c))) return TRACE_RETURN (false);
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001695 unsigned int offset = get_offset ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001696 if (unlikely (!offset)) return TRACE_RETURN (true);
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001697 return TRACE_RETURN (StructAtOffset<PosLookupSubTable> (this, offset).sanitize (c, get_type ()));
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001698}
1699
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001700static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
Behdad Esfahbod4c44d832009-05-19 23:42:30 -04001701{
Behdad Esfahbodea278d32012-07-27 02:12:28 -04001702 const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001703 const PosLookup &l = gpos.get_lookup (lookup_index);
1704
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001705 if (unlikely (c->nesting_level_left == 0))
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001706 return false;
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001707
Behdad Esfahbod650ac002012-04-23 13:17:09 -04001708 hb_apply_context_t new_c (*c);
1709 new_c.nesting_level_left--;
1710 new_c.set_lookup (l);
Behdad Esfahbod41ae6742012-04-11 17:11:05 -04001711 return l.apply_once (&new_c);
Behdad Esfahbod5e5eb052009-05-18 17:09:33 -04001712}
1713
1714
Behdad Esfahbod194d4562010-10-27 23:09:10 -04001715#undef attach_lookback
1716#undef cursive_chain
1717
1718
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001719
Behdad Esfahbod7a750ac2011-08-17 14:19:59 +02001720#endif /* HB_OT_LAYOUT_GPOS_TABLE_HH */