blob: c4e8a786cced379a056426b9020e186fcde091f6 [file] [log] [blame]
Behdad Esfahboda2a9a022008-01-15 22:46:32 +00001/*
2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg
3 * Copyright (C) 2006 Behdad Esfahbod
4 * Copyright (C) 2007 Red Hat, Inc.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +00006 * This is part of HarfBuzz, an OpenType Layout engine library.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00007 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +00008 * Permission is hereby granted, without written agreement and without
9 * license or royalty fees, to use, copy, modify, and distribute this
10 * software and its documentation for any purpose, provided that the
11 * above copyright notice and the following two paragraphs appear in
12 * all copies of this software.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000013 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +000014 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * DAMAGE.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000019 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +000020 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000025 *
Behdad Esfahboda2a9a022008-01-15 22:46:32 +000026 * Red Hat Author(s): Behdad Esfahbod
27 */
28
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000029#include "harfbuzz-impl.h"
30#include "harfbuzz-gpos-private.h"
31#include "harfbuzz-open-private.h"
32#include "harfbuzz-gdef-private.h"
33
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000034struct GPOS_Instance_
35{
36 HB_GPOSHeader* gpos;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000037 HB_Font font;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000038 HB_Bool dvi;
39 HB_UShort load_flags; /* how the glyph should be loaded */
40 HB_Bool r2l;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000041
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000042 HB_UShort last; /* the last valid glyph -- used
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000043 with cursive positioning */
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000044 HB_Fixed anchor_x; /* the coordinates of the anchor point */
45 HB_Fixed anchor_y; /* of the last valid glyph */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000046};
47
48typedef struct GPOS_Instance_ GPOS_Instance;
49
50
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +000051static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000052 HB_UShort lookup_index,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000053 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000054 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000055 int nesting_level );
56
57
58
59/* the client application must replace this with something more
60 meaningful if multiple master fonts are to be supported. */
61
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000062static HB_Error default_mmfunc( HB_Font font,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000063 HB_UShort metric_id,
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000064 HB_Fixed* metric_value,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000065 void* data )
66{
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000067 HB_UNUSED(font);
Behdad Esfahbod4280ec42007-10-25 00:23:46 +000068 HB_UNUSED(metric_id);
69 HB_UNUSED(metric_value);
70 HB_UNUSED(data);
Behdad Esfahbod282c60a2007-10-25 23:22:17 +000071 return ERR(HB_Err_Not_Covered); /* ERR() call intended */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000072}
73
74
75
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000076HB_Error HB_Load_GPOS_Table( HB_Font font,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000077 HB_GPOSHeader** retptr,
Behdad Esfahbodce48f032009-11-02 14:35:51 -050078 hb_ot_layout_t *layout )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000079{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +000080 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000081
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000082 HB_GPOSHeader* gpos;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000083
Behdad Esfahbod47d2c332007-11-07 09:59:18 +000084 HB_Stream stream = font->stream;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +000085 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000086
87
Behdad Esfahbodce48f032009-11-02 14:35:51 -050088 if ( !retptr || !layout )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +000089 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000090
Behdad Esfahbod4280ec42007-10-25 00:23:46 +000091 if ( GOTO_Table( TTAG_GPOS ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +000092 return error;
93
94 base_offset = FILE_Pos();
95
96 if ( ALLOC ( gpos, sizeof( *gpos ) ) )
97 return error;
98
Behdad Esfahbod719f9ea2008-12-26 02:31:35 +000099 gpos->gfunc = (HB_GlyphFunction) FT_Load_Glyph;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000100 gpos->mmfunc = default_mmfunc;
101
102 /* skip version */
103
104 if ( FILE_Seek( base_offset + 4L ) ||
105 ACCESS_Frame( 2L ) )
106 goto Fail4;
107
108 new_offset = GET_UShort() + base_offset;
109
110 FORGET_Frame();
111
112 cur_offset = FILE_Pos();
113 if ( FILE_Seek( new_offset ) ||
114 ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000115 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000116 goto Fail4;
117 (void)FILE_Seek( cur_offset );
118
119 if ( ACCESS_Frame( 2L ) )
120 goto Fail3;
121
122 new_offset = GET_UShort() + base_offset;
123
124 FORGET_Frame();
125
126 cur_offset = FILE_Pos();
127 if ( FILE_Seek( new_offset ) ||
128 ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000129 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000130 goto Fail3;
131 (void)FILE_Seek( cur_offset );
132
133 if ( ACCESS_Frame( 2L ) )
134 goto Fail2;
135
136 new_offset = GET_UShort() + base_offset;
137
138 FORGET_Frame();
139
140 cur_offset = FILE_Pos();
141 if ( FILE_Seek( new_offset ) ||
142 ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000143 stream, HB_Type_GPOS ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000144 goto Fail2;
145
Behdad Esfahbodce48f032009-11-02 14:35:51 -0500146 gpos->layout = layout; /* can be NULL */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000147
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000148 *retptr = gpos;
149
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000150 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000151
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000152Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000153 _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000154
155Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000156 _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000157
158Fail4:
159 FREE( gpos );
160
161 return error;
162}
163
164
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000165HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000166{
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000167 _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
168 _HB_OPEN_Free_FeatureList( &gpos->FeatureList );
169 _HB_OPEN_Free_ScriptList( &gpos->ScriptList );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000170
Behdad Esfahbod7341a112007-04-03 22:45:29 +0000171 FREE( gpos );
172
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000173 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000174}
175
176
177/*****************************
178 * SubTable related functions
179 *****************************/
180
181/* shared tables */
182
183/* ValueRecord */
184
185/* There is a subtle difference in the specs between a `table' and a
186 `record' -- offsets for device tables in ValueRecords are taken from
187 the parent table and not the parent record. */
188
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000189static HB_Error Load_ValueRecord( HB_ValueRecord* vr,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000190 HB_UShort format,
191 HB_UInt base_offset,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +0000192 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000193{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000194 HB_Error error;
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +0000195
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000196 HB_UInt cur_offset, new_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000197
198
199 if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
200 {
201 if ( ACCESS_Frame( 2L ) )
202 return error;
203
204 vr->XPlacement = GET_Short();
205
206 FORGET_Frame();
207 }
208 else
209 vr->XPlacement = 0;
210
211 if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
212 {
213 if ( ACCESS_Frame( 2L ) )
214 return error;
215
216 vr->YPlacement = GET_Short();
217
218 FORGET_Frame();
219 }
220 else
221 vr->YPlacement = 0;
222
223 if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
224 {
225 if ( ACCESS_Frame( 2L ) )
226 return error;
227
228 vr->XAdvance = GET_Short();
229
230 FORGET_Frame();
231 }
232 else
233 vr->XAdvance = 0;
234
235 if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
236 {
237 if ( ACCESS_Frame( 2L ) )
238 return error;
239
240 vr->YAdvance = GET_Short();
241
242 FORGET_Frame();
243 }
244 else
245 vr->YAdvance = 0;
246
247 if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
248 {
249 if ( ACCESS_Frame( 2L ) )
250 return error;
251
252 new_offset = GET_UShort();
253
254 FORGET_Frame();
255
256 if ( new_offset )
257 {
258 new_offset += base_offset;
259
260 cur_offset = FILE_Pos();
261 if ( FILE_Seek( new_offset ) ||
262 ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000263 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000264 return error;
265 (void)FILE_Seek( cur_offset );
266 }
267 else
268 goto empty1;
269 }
270 else
271 {
272 empty1:
273 vr->XPlacementDevice.StartSize = 0;
274 vr->XPlacementDevice.EndSize = 0;
275 vr->XPlacementDevice.DeltaValue = NULL;
276 }
277
278 if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
279 {
280 if ( ACCESS_Frame( 2L ) )
281 goto Fail3;
282
283 new_offset = GET_UShort();
284
285 FORGET_Frame();
286
287 if ( new_offset )
288 {
289 new_offset += base_offset;
290
291 cur_offset = FILE_Pos();
292 if ( FILE_Seek( new_offset ) ||
293 ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000294 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000295 goto Fail3;
296 (void)FILE_Seek( cur_offset );
297 }
298 else
299 goto empty2;
300 }
301 else
302 {
303 empty2:
304 vr->YPlacementDevice.StartSize = 0;
305 vr->YPlacementDevice.EndSize = 0;
306 vr->YPlacementDevice.DeltaValue = NULL;
307 }
308
309 if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
310 {
311 if ( ACCESS_Frame( 2L ) )
312 goto Fail2;
313
314 new_offset = GET_UShort();
315
316 FORGET_Frame();
317
318 if ( new_offset )
319 {
320 new_offset += base_offset;
321
322 cur_offset = FILE_Pos();
323 if ( FILE_Seek( new_offset ) ||
324 ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000325 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000326 goto Fail2;
327 (void)FILE_Seek( cur_offset );
328 }
329 else
330 goto empty3;
331 }
332 else
333 {
334 empty3:
335 vr->XAdvanceDevice.StartSize = 0;
336 vr->XAdvanceDevice.EndSize = 0;
337 vr->XAdvanceDevice.DeltaValue = NULL;
338 }
339
340 if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
341 {
342 if ( ACCESS_Frame( 2L ) )
343 goto Fail1;
344
345 new_offset = GET_UShort();
346
347 FORGET_Frame();
348
349 if ( new_offset )
350 {
351 new_offset += base_offset;
352
353 cur_offset = FILE_Pos();
354 if ( FILE_Seek( new_offset ) ||
355 ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000356 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000357 goto Fail1;
358 (void)FILE_Seek( cur_offset );
359 }
360 else
361 goto empty4;
362 }
363 else
364 {
365 empty4:
366 vr->YAdvanceDevice.StartSize = 0;
367 vr->YAdvanceDevice.EndSize = 0;
368 vr->YAdvanceDevice.DeltaValue = NULL;
369 }
370
371 if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
372 {
373 if ( ACCESS_Frame( 2L ) )
374 goto Fail1;
375
376 vr->XIdPlacement = GET_UShort();
377
378 FORGET_Frame();
379 }
380 else
381 vr->XIdPlacement = 0;
382
383 if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
384 {
385 if ( ACCESS_Frame( 2L ) )
386 goto Fail1;
387
388 vr->YIdPlacement = GET_UShort();
389
390 FORGET_Frame();
391 }
392 else
393 vr->YIdPlacement = 0;
394
395 if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
396 {
397 if ( ACCESS_Frame( 2L ) )
398 goto Fail1;
399
400 vr->XIdAdvance = GET_UShort();
401
402 FORGET_Frame();
403 }
404 else
405 vr->XIdAdvance = 0;
406
407 if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
408 {
409 if ( ACCESS_Frame( 2L ) )
410 goto Fail1;
411
412 vr->YIdAdvance = GET_UShort();
413
414 FORGET_Frame();
415 }
416 else
417 vr->YIdAdvance = 0;
418
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000419 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000420
421Fail1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000422 _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000423
424Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000425 _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000426
427Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000428 _HB_OPEN_Free_Device( &vr->YPlacementDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000429 return error;
430}
431
432
433static void Free_ValueRecord( HB_ValueRecord* vr,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000434 HB_UShort format )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000435{
436 if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000437 _HB_OPEN_Free_Device( &vr->YAdvanceDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000438 if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000439 _HB_OPEN_Free_Device( &vr->XAdvanceDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000440 if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000441 _HB_OPEN_Free_Device( &vr->YPlacementDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000442 if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000443 _HB_OPEN_Free_Device( &vr->XPlacementDevice );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000444}
445
446
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000447static HB_Error Get_ValueRecord( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000448 HB_ValueRecord* vr,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000449 HB_UShort format,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000450 HB_Position gd )
451{
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000452 HB_Fixed value;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000453 HB_Short pixel_value;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000454 HB_Error error = HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000455 HB_GPOSHeader* gpos = gpi->gpos;
456
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000457 HB_UShort x_ppem, y_ppem;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000458 HB_16Dot16 x_scale, y_scale;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000459
460
461 if ( !format )
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000462 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000463
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000464 x_ppem = gpi->font->size->metrics.x_ppem;
465 y_ppem = gpi->font->size->metrics.y_ppem;
466 x_scale = gpi->font->size->metrics.x_scale;
467 y_scale = gpi->font->size->metrics.y_scale;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000468
469 /* design units -> fractional pixel */
470
471 if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
472 gd->x_pos += x_scale * vr->XPlacement / 0x10000;
473 if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
474 gd->y_pos += y_scale * vr->YPlacement / 0x10000;
475 if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
476 gd->x_advance += x_scale * vr->XAdvance / 0x10000;
477 if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
478 gd->y_advance += y_scale * vr->YAdvance / 0x10000;
479
480 if ( !gpi->dvi )
481 {
482 /* pixel -> fractional pixel */
483
484 if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
485 {
486 _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
487 gd->x_pos += pixel_value << 6;
488 }
489 if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
490 {
491 _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
492 gd->y_pos += pixel_value << 6;
493 }
494 if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
495 {
496 _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
497 gd->x_advance += pixel_value << 6;
498 }
499 if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
500 {
501 _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
502 gd->y_advance += pixel_value << 6;
503 }
504 }
505
506 /* values returned from mmfunc() are already in fractional pixels */
507
508 if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
509 {
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000510 error = (gpos->mmfunc)( gpi->font, vr->XIdPlacement,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000511 &value, gpos->data );
512 if ( error )
513 return error;
514 gd->x_pos += value;
515 }
516 if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
517 {
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000518 error = (gpos->mmfunc)( gpi->font, vr->YIdPlacement,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000519 &value, gpos->data );
520 if ( error )
521 return error;
522 gd->y_pos += value;
523 }
524 if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
525 {
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000526 error = (gpos->mmfunc)( gpi->font, vr->XIdAdvance,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000527 &value, gpos->data );
528 if ( error )
529 return error;
530 gd->x_advance += value;
531 }
532 if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
533 {
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000534 error = (gpos->mmfunc)( gpi->font, vr->YIdAdvance,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000535 &value, gpos->data );
536 if ( error )
537 return error;
538 gd->y_advance += value;
539 }
540
541 return error;
542}
543
544
545/* AnchorFormat1 */
546/* AnchorFormat2 */
547/* AnchorFormat3 */
548/* AnchorFormat4 */
549
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000550static HB_Error Load_Anchor( HB_Anchor* an,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +0000551 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000552{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000553 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000554
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000555 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000556
557
558 base_offset = FILE_Pos();
559
560 if ( ACCESS_Frame( 2L ) )
561 return error;
562
563 an->PosFormat = GET_UShort();
564
565 FORGET_Frame();
566
567 switch ( an->PosFormat )
568 {
569 case 1:
570 if ( ACCESS_Frame( 4L ) )
571 return error;
572
573 an->af.af1.XCoordinate = GET_Short();
574 an->af.af1.YCoordinate = GET_Short();
575
576 FORGET_Frame();
577 break;
578
579 case 2:
580 if ( ACCESS_Frame( 6L ) )
581 return error;
582
583 an->af.af2.XCoordinate = GET_Short();
584 an->af.af2.YCoordinate = GET_Short();
585 an->af.af2.AnchorPoint = GET_UShort();
586
587 FORGET_Frame();
588 break;
589
590 case 3:
591 if ( ACCESS_Frame( 6L ) )
592 return error;
593
594 an->af.af3.XCoordinate = GET_Short();
595 an->af.af3.YCoordinate = GET_Short();
596
597 new_offset = GET_UShort();
598
599 FORGET_Frame();
600
601 if ( new_offset )
602 {
603 new_offset += base_offset;
604
605 cur_offset = FILE_Pos();
606 if ( FILE_Seek( new_offset ) ||
607 ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000608 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000609 return error;
610 (void)FILE_Seek( cur_offset );
611 }
612 else
613 {
614 an->af.af3.XDeviceTable.StartSize = 0;
615 an->af.af3.XDeviceTable.EndSize = 0;
616 an->af.af3.XDeviceTable.DeltaValue = NULL;
617 }
618
619 if ( ACCESS_Frame( 2L ) )
620 goto Fail;
621
622 new_offset = GET_UShort();
623
624 FORGET_Frame();
625
626 if ( new_offset )
627 {
628 new_offset += base_offset;
629
630 cur_offset = FILE_Pos();
631 if ( FILE_Seek( new_offset ) ||
632 ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000633 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000634 goto Fail;
635 (void)FILE_Seek( cur_offset );
636 }
637 else
638 {
639 an->af.af3.YDeviceTable.StartSize = 0;
640 an->af.af3.YDeviceTable.EndSize = 0;
641 an->af.af3.YDeviceTable.DeltaValue = NULL;
642 }
643 break;
644
645 case 4:
646 if ( ACCESS_Frame( 4L ) )
647 return error;
648
649 an->af.af4.XIdAnchor = GET_UShort();
650 an->af.af4.YIdAnchor = GET_UShort();
651
652 FORGET_Frame();
653 break;
654
655 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +0000656 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000657 }
658
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000659 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000660
661Fail:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000662 _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000663 return error;
664}
665
666
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000667static void Free_Anchor( HB_Anchor* an )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000668{
669 if ( an->PosFormat == 3 )
670 {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000671 _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable );
672 _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000673 }
674}
675
676
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000677static HB_Error Get_Anchor( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000678 HB_Anchor* an,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000679 HB_UShort glyph_index,
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000680 HB_Fixed* x_value,
681 HB_Fixed* y_value )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000682{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000683 HB_Error error = HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000684
685 FT_Outline outline;
686 HB_GPOSHeader* gpos = gpi->gpos;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000687 HB_UShort ap;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000688
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000689 HB_Short pixel_value;
690 HB_UShort load_flags;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000691
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000692 HB_UShort x_ppem, y_ppem;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000693 HB_16Dot16 x_scale, y_scale;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000694
695
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000696 x_ppem = gpi->font->size->metrics.x_ppem;
697 y_ppem = gpi->font->size->metrics.y_ppem;
698 x_scale = gpi->font->size->metrics.x_scale;
699 y_scale = gpi->font->size->metrics.y_scale;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000700
701 switch ( an->PosFormat )
702 {
703 case 0:
704 /* The special case of an empty AnchorTable */
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000705 default:
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000706
707 return HB_Err_Not_Covered;
708
709 case 1:
710 *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
711 *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
712 break;
713
714 case 2:
715 /* glyphs must be scaled */
716
717 load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE;
718
719 if ( !gpi->dvi )
720 {
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000721 error = (gpos->gfunc)( gpi->font, glyph_index, load_flags );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000722 if ( error )
723 return error;
724
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000725 if ( gpi->font->glyph->format != ft_glyph_format_outline )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +0000726 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000727
728 ap = an->af.af2.AnchorPoint;
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +0000729
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000730 outline = gpi->font->glyph->outline;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000731
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000732 /* if n_points is set to zero, we use the design coordinate value pair.
733 * This can happen e.g. for sbit glyphs. */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000734 if ( !outline.n_points )
735 goto no_contour_point;
736
737 if ( ap >= outline.n_points )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +0000738 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000739
740 *x_value = outline.points[ap].x;
741 *y_value = outline.points[ap].y;
742 }
743 else
744 {
745 no_contour_point:
746 *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
747 *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
748 }
749 break;
750
751 case 3:
752 if ( !gpi->dvi )
753 {
754 _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
755 *x_value = pixel_value << 6;
756 _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
757 *y_value = pixel_value << 6;
758 }
759 else
760 *x_value = *y_value = 0;
761
762 *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
763 *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
764 break;
765
766 case 4:
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000767 error = (gpos->mmfunc)( gpi->font, an->af.af4.XIdAnchor,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000768 x_value, gpos->data );
769 if ( error )
770 return error;
771
Behdad Esfahbod47d2c332007-11-07 09:59:18 +0000772 error = (gpos->mmfunc)( gpi->font, an->af.af4.YIdAnchor,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000773 y_value, gpos->data );
774 if ( error )
775 return error;
776 break;
777 }
778
779 return error;
780}
781
782
783/* MarkArray */
784
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000785static HB_Error Load_MarkArray ( HB_MarkArray* ma,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +0000786 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000787{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000788 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000789
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000790 HB_UShort n, m, count;
791 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000792
793 HB_MarkRecord* mr;
794
795
796 base_offset = FILE_Pos();
797
798 if ( ACCESS_Frame( 2L ) )
799 return error;
800
801 count = ma->MarkCount = GET_UShort();
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +0000802
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000803 FORGET_Frame();
804
805 ma->MarkRecord = NULL;
806
807 if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )
808 return error;
809
810 mr = ma->MarkRecord;
811
812 for ( n = 0; n < count; n++ )
813 {
814 if ( ACCESS_Frame( 4L ) )
815 goto Fail;
816
817 mr[n].Class = GET_UShort();
818 new_offset = GET_UShort() + base_offset;
819
820 FORGET_Frame();
821
822 cur_offset = FILE_Pos();
823 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000824 ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000825 goto Fail;
826 (void)FILE_Seek( cur_offset );
827 }
828
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000829 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000830
831Fail:
832 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000833 Free_Anchor( &mr[m].MarkAnchor );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000834
835 FREE( mr );
836 return error;
837}
838
839
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000840static void Free_MarkArray( HB_MarkArray* ma )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000841{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000842 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000843
844 HB_MarkRecord* mr;
845
846
847 if ( ma->MarkRecord )
848 {
849 count = ma->MarkCount;
850 mr = ma->MarkRecord;
851
852 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000853 Free_Anchor( &mr[n].MarkAnchor );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000854
855 FREE( mr );
856 }
857}
858
859
860/* LookupType 1 */
861
862/* SinglePosFormat1 */
863/* SinglePosFormat2 */
864
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000865static HB_Error Load_SinglePos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +0000866 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000867{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000868 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000869 HB_SinglePos* sp = &st->single;
870
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000871 HB_UShort n, m, count, format;
872 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000873
874 HB_ValueRecord* vr;
875
876
877 base_offset = FILE_Pos();
878
879 if ( ACCESS_Frame( 6L ) )
880 return error;
881
882 sp->PosFormat = GET_UShort();
883 new_offset = GET_UShort() + base_offset;
884
885 format = sp->ValueFormat = GET_UShort();
886
887 FORGET_Frame();
888
889 if ( !format )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +0000890 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000891
892 cur_offset = FILE_Pos();
893 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000894 ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000895 return error;
896 (void)FILE_Seek( cur_offset );
897
898 switch ( sp->PosFormat )
899 {
900 case 1:
901 error = Load_ValueRecord( &sp->spf.spf1.Value, format,
902 base_offset, stream );
903 if ( error )
904 goto Fail2;
905 break;
906
907 case 2:
908 if ( ACCESS_Frame( 2L ) )
909 goto Fail2;
910
911 count = sp->spf.spf2.ValueCount = GET_UShort();
912
913 FORGET_Frame();
914
915 sp->spf.spf2.Value = NULL;
916
917 if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )
918 goto Fail2;
919
920 vr = sp->spf.spf2.Value;
921
922 for ( n = 0; n < count; n++ )
923 {
924 error = Load_ValueRecord( &vr[n], format, base_offset, stream );
925 if ( error )
926 goto Fail1;
927 }
928 break;
929
930 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +0000931 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000932 }
933
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000934 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000935
936Fail1:
937 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000938 Free_ValueRecord( &vr[m], format );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000939
940 FREE( vr );
941
942Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000943 _HB_OPEN_Free_Coverage( &sp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000944 return error;
945}
946
947
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000948static void Free_SinglePos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000949{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000950 HB_UShort n, count, format;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000951 HB_SinglePos* sp = &st->single;
952
953 HB_ValueRecord* v;
954
955
956 format = sp->ValueFormat;
957
958 switch ( sp->PosFormat )
959 {
960 case 1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000961 Free_ValueRecord( &sp->spf.spf1.Value, format );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000962 break;
963
964 case 2:
965 if ( sp->spf.spf2.Value )
966 {
967 count = sp->spf.spf2.ValueCount;
968 v = sp->spf.spf2.Value;
969
970 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000971 Free_ValueRecord( &v[n], format );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000972
973 FREE( v );
974 }
975 break;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000976 default:
977 break;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000978 }
979
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +0000980 _HB_OPEN_Free_Coverage( &sp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000981}
982
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000983static HB_Error Lookup_SinglePos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000984 HB_GPOS_SubTable* st,
985 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000986 HB_UShort flags,
987 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000988 int nesting_level )
989{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +0000990 HB_UShort index, property;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +0000991 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000992 HB_GPOSHeader* gpos = gpi->gpos;
993 HB_SinglePos* sp = &st->single;
994
Behdad Esfahbod4280ec42007-10-25 00:23:46 +0000995 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +0000996
997 if ( context_length != 0xFFFF && context_length < 1 )
998 return HB_Err_Not_Covered;
999
Behdad Esfahbodce48f032009-11-02 14:35:51 -05001000 if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001001 return error;
1002
1003 error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
1004 if ( error )
1005 return error;
1006
1007 switch ( sp->PosFormat )
1008 {
1009 case 1:
1010 error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
1011 sp->ValueFormat, POSITION( buffer->in_pos ) );
1012 if ( error )
1013 return error;
1014 break;
1015
1016 case 2:
1017 if ( index >= sp->spf.spf2.ValueCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001018 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001019 error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
1020 sp->ValueFormat, POSITION( buffer->in_pos ) );
1021 if ( error )
1022 return error;
1023 break;
1024
1025 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001026 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001027 }
1028
1029 (buffer->in_pos)++;
1030
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001031 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001032}
1033
1034
1035/* LookupType 2 */
1036
1037/* PairSet */
1038
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001039static HB_Error Load_PairSet ( HB_PairSet* ps,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001040 HB_UShort format1,
1041 HB_UShort format2,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001042 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001043{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001044 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001045
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001046 HB_UShort n, m, count;
1047 HB_UInt base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001048
1049 HB_PairValueRecord* pvr;
1050
1051
1052 base_offset = FILE_Pos();
1053
1054 if ( ACCESS_Frame( 2L ) )
1055 return error;
1056
1057 count = ps->PairValueCount = GET_UShort();
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00001058
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001059 FORGET_Frame();
1060
1061 ps->PairValueRecord = NULL;
1062
1063 if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )
1064 return error;
1065
1066 pvr = ps->PairValueRecord;
1067
1068 for ( n = 0; n < count; n++ )
1069 {
1070 if ( ACCESS_Frame( 2L ) )
1071 goto Fail;
1072
1073 pvr[n].SecondGlyph = GET_UShort();
1074
1075 FORGET_Frame();
1076
1077 if ( format1 )
1078 {
1079 error = Load_ValueRecord( &pvr[n].Value1, format1,
1080 base_offset, stream );
1081 if ( error )
1082 goto Fail;
1083 }
1084 if ( format2 )
1085 {
1086 error = Load_ValueRecord( &pvr[n].Value2, format2,
1087 base_offset, stream );
1088 if ( error )
1089 {
1090 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001091 Free_ValueRecord( &pvr[n].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001092 goto Fail;
1093 }
1094 }
1095 }
1096
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001097 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001098
1099Fail:
1100 for ( m = 0; m < n; m++ )
1101 {
1102 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001103 Free_ValueRecord( &pvr[m].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001104 if ( format2 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001105 Free_ValueRecord( &pvr[m].Value2, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001106 }
1107
1108 FREE( pvr );
1109 return error;
1110}
1111
1112
1113static void Free_PairSet( HB_PairSet* ps,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001114 HB_UShort format1,
1115 HB_UShort format2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001116{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001117 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001118
1119 HB_PairValueRecord* pvr;
1120
1121
1122 if ( ps->PairValueRecord )
1123 {
1124 count = ps->PairValueCount;
1125 pvr = ps->PairValueRecord;
1126
1127 for ( n = 0; n < count; n++ )
1128 {
1129 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001130 Free_ValueRecord( &pvr[n].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001131 if ( format2 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001132 Free_ValueRecord( &pvr[n].Value2, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001133 }
1134
1135 FREE( pvr );
1136 }
1137}
1138
1139
1140/* PairPosFormat1 */
1141
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001142static HB_Error Load_PairPos1( HB_PairPosFormat1* ppf1,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001143 HB_UShort format1,
1144 HB_UShort format2,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001145 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001146{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001147 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001148
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001149 HB_UShort n, m, count;
1150 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001151
1152 HB_PairSet* ps;
1153
1154
1155 base_offset = FILE_Pos() - 8L;
1156
1157 if ( ACCESS_Frame( 2L ) )
1158 return error;
1159
1160 count = ppf1->PairSetCount = GET_UShort();
1161
1162 FORGET_Frame();
1163
1164 ppf1->PairSet = NULL;
1165
1166 if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )
1167 return error;
1168
1169 ps = ppf1->PairSet;
1170
1171 for ( n = 0; n < count; n++ )
1172 {
1173 if ( ACCESS_Frame( 2L ) )
1174 goto Fail;
1175
1176 new_offset = GET_UShort() + base_offset;
1177
1178 FORGET_Frame();
1179
1180 cur_offset = FILE_Pos();
1181 if ( FILE_Seek( new_offset ) ||
1182 ( error = Load_PairSet( &ps[n], format1,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001183 format2, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001184 goto Fail;
1185 (void)FILE_Seek( cur_offset );
1186 }
1187
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001188 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001189
1190Fail:
1191 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001192 Free_PairSet( &ps[m], format1, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001193
1194 FREE( ps );
1195 return error;
1196}
1197
1198
1199static void Free_PairPos1( HB_PairPosFormat1* ppf1,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001200 HB_UShort format1,
1201 HB_UShort format2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001202{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001203 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001204
1205 HB_PairSet* ps;
1206
1207
1208 if ( ppf1->PairSet )
1209 {
1210 count = ppf1->PairSetCount;
1211 ps = ppf1->PairSet;
1212
1213 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001214 Free_PairSet( &ps[n], format1, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001215
1216 FREE( ps );
1217 }
1218}
1219
1220
1221/* PairPosFormat2 */
1222
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001223static HB_Error Load_PairPos2( HB_PairPosFormat2* ppf2,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001224 HB_UShort format1,
1225 HB_UShort format2,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001226 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001227{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001228 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001229
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001230 HB_UShort m, n, k, count1, count2;
1231 HB_UInt cur_offset, new_offset1, new_offset2, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001232
1233 HB_Class1Record* c1r;
1234 HB_Class2Record* c2r;
1235
1236
1237 base_offset = FILE_Pos() - 8L;
1238
1239 if ( ACCESS_Frame( 8L ) )
1240 return error;
1241
1242 new_offset1 = GET_UShort() + base_offset;
1243 new_offset2 = GET_UShort() + base_offset;
1244
1245 /* `Class1Count' and `Class2Count' are the upper limits for class
1246 values, thus we read it now to make additional safety checks. */
1247
1248 count1 = ppf2->Class1Count = GET_UShort();
1249 count2 = ppf2->Class2Count = GET_UShort();
1250
1251 FORGET_Frame();
1252
1253 cur_offset = FILE_Pos();
1254 if ( FILE_Seek( new_offset1 ) ||
1255 ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001256 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001257 return error;
1258 if ( FILE_Seek( new_offset2 ) ||
1259 ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001260 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001261 goto Fail3;
1262 (void)FILE_Seek( cur_offset );
1263
1264 ppf2->Class1Record = NULL;
1265
1266 if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
1267 goto Fail2;
1268
1269 c1r = ppf2->Class1Record;
1270
1271 for ( m = 0; m < count1; m++ )
1272 {
1273 c1r[m].Class2Record = NULL;
1274
1275 if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
1276 goto Fail1;
1277
1278 c2r = c1r[m].Class2Record;
1279
1280 for ( n = 0; n < count2; n++ )
1281 {
1282 if ( format1 )
1283 {
1284 error = Load_ValueRecord( &c2r[n].Value1, format1,
1285 base_offset, stream );
1286 if ( error )
1287 goto Fail0;
1288 }
1289 if ( format2 )
1290 {
1291 error = Load_ValueRecord( &c2r[n].Value2, format2,
1292 base_offset, stream );
1293 if ( error )
1294 {
1295 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001296 Free_ValueRecord( &c2r[n].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001297 goto Fail0;
1298 }
1299 }
1300 }
1301
1302 continue;
1303
1304 Fail0:
1305 for ( k = 0; k < n; k++ )
1306 {
1307 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001308 Free_ValueRecord( &c2r[k].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001309 if ( format2 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001310 Free_ValueRecord( &c2r[k].Value2, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001311 }
1312 goto Fail1;
1313 }
1314
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001315 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001316
1317Fail1:
1318 for ( k = 0; k < m; k++ )
1319 {
1320 c2r = c1r[k].Class2Record;
1321
1322 for ( n = 0; n < count2; n++ )
1323 {
1324 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001325 Free_ValueRecord( &c2r[n].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001326 if ( format2 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001327 Free_ValueRecord( &c2r[n].Value2, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001328 }
1329
1330 FREE( c2r );
1331 }
1332
1333 FREE( c1r );
1334Fail2:
1335
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001336 _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001337
1338Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001339 _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001340 return error;
1341}
1342
1343
1344static void Free_PairPos2( HB_PairPosFormat2* ppf2,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001345 HB_UShort format1,
1346 HB_UShort format2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001347{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001348 HB_UShort m, n, count1, count2;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001349
1350 HB_Class1Record* c1r;
1351 HB_Class2Record* c2r;
1352
1353
1354 if ( ppf2->Class1Record )
1355 {
1356 c1r = ppf2->Class1Record;
1357 count1 = ppf2->Class1Count;
1358 count2 = ppf2->Class2Count;
1359
1360 for ( m = 0; m < count1; m++ )
1361 {
1362 c2r = c1r[m].Class2Record;
1363
1364 for ( n = 0; n < count2; n++ )
1365 {
1366 if ( format1 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001367 Free_ValueRecord( &c2r[n].Value1, format1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001368 if ( format2 )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001369 Free_ValueRecord( &c2r[n].Value2, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001370 }
1371
1372 FREE( c2r );
1373 }
1374
1375 FREE( c1r );
1376
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001377 _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2 );
1378 _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001379 }
1380}
1381
1382
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001383static HB_Error Load_PairPos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001384 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001385{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001386 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001387 HB_PairPos* pp = &st->pair;
1388
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001389 HB_UShort format1, format2;
1390 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001391
1392
1393 base_offset = FILE_Pos();
1394
1395 if ( ACCESS_Frame( 8L ) )
1396 return error;
1397
1398 pp->PosFormat = GET_UShort();
1399 new_offset = GET_UShort() + base_offset;
1400
1401 format1 = pp->ValueFormat1 = GET_UShort();
1402 format2 = pp->ValueFormat2 = GET_UShort();
1403
1404 FORGET_Frame();
1405
1406 cur_offset = FILE_Pos();
1407 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001408 ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001409 return error;
1410 (void)FILE_Seek( cur_offset );
1411
1412 switch ( pp->PosFormat )
1413 {
1414 case 1:
1415 error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
1416 if ( error )
1417 goto Fail;
1418 break;
1419
1420 case 2:
1421 error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
1422 if ( error )
1423 goto Fail;
1424 break;
1425
1426 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001427 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001428 }
1429
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001430 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001431
1432Fail:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001433 _HB_OPEN_Free_Coverage( &pp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001434 return error;
1435}
1436
1437
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001438static void Free_PairPos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001439{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001440 HB_UShort format1, format2;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001441 HB_PairPos* pp = &st->pair;
1442
1443
1444 format1 = pp->ValueFormat1;
1445 format2 = pp->ValueFormat2;
1446
1447 switch ( pp->PosFormat )
1448 {
1449 case 1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001450 Free_PairPos1( &pp->ppf.ppf1, format1, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001451 break;
1452
1453 case 2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001454 Free_PairPos2( &pp->ppf.ppf2, format1, format2 );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001455 break;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001456
1457 default:
1458 break;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001459 }
1460
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001461 _HB_OPEN_Free_Coverage( &pp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001462}
1463
1464
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001465static HB_Error Lookup_PairPos1( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001466 HB_PairPosFormat1* ppf1,
1467 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001468 HB_UInt first_pos,
1469 HB_UShort index,
1470 HB_UShort format1,
1471 HB_UShort format2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001472{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001473 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001474 HB_UShort numpvr, glyph2;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001475
1476 HB_PairValueRecord* pvr;
1477
1478
1479 if ( index >= ppf1->PairSetCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001480 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001481
1482 pvr = ppf1->PairSet[index].PairValueRecord;
1483 if ( !pvr )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001484 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001485
1486 glyph2 = IN_CURGLYPH();
1487
1488 for ( numpvr = ppf1->PairSet[index].PairValueCount;
1489 numpvr;
1490 numpvr--, pvr++ )
1491 {
1492 if ( glyph2 == pvr->SecondGlyph )
1493 {
1494 error = Get_ValueRecord( gpi, &pvr->Value1, format1,
1495 POSITION( first_pos ) );
1496 if ( error )
1497 return error;
1498 return Get_ValueRecord( gpi, &pvr->Value2, format2,
1499 POSITION( buffer->in_pos ) );
1500 }
1501 }
1502
1503 return HB_Err_Not_Covered;
1504}
1505
1506
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001507static HB_Error Lookup_PairPos2( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001508 HB_PairPosFormat2* ppf2,
1509 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001510 HB_UInt first_pos,
1511 HB_UShort format1,
1512 HB_UShort format2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001513{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001514 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001515 HB_UShort cl1 = 0, cl2 = 0; /* shut compiler up */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001516
1517 HB_Class1Record* c1r;
1518 HB_Class2Record* c2r;
1519
1520
1521 error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
1522 &cl1, NULL );
1523 if ( error && error != HB_Err_Not_Covered )
1524 return error;
1525 error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
1526 &cl2, NULL );
1527 if ( error && error != HB_Err_Not_Covered )
1528 return error;
1529
1530 c1r = &ppf2->Class1Record[cl1];
1531 if ( !c1r )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001532 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001533 c2r = &c1r->Class2Record[cl2];
1534
1535 error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
1536 if ( error )
1537 return error;
1538 return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
1539}
1540
1541
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001542static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001543 HB_GPOS_SubTable* st,
1544 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001545 HB_UShort flags,
1546 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001547 int nesting_level )
1548{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001549 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001550 HB_UShort index, property;
1551 HB_UInt first_pos;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001552 HB_GPOSHeader* gpos = gpi->gpos;
1553 HB_PairPos* pp = &st->pair;
1554
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001555 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001556
1557 if ( buffer->in_pos >= buffer->in_length - 1 )
1558 return HB_Err_Not_Covered; /* Not enough glyphs in stream */
1559
1560 if ( context_length != 0xFFFF && context_length < 2 )
1561 return HB_Err_Not_Covered;
1562
Behdad Esfahbodce48f032009-11-02 14:35:51 -05001563 if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001564 return error;
1565
1566 error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
1567 if ( error )
1568 return error;
1569
1570 /* second glyph */
1571
1572 first_pos = buffer->in_pos;
1573 (buffer->in_pos)++;
1574
Behdad Esfahbodce48f032009-11-02 14:35:51 -05001575 while ( CHECK_Property( gpos->layout, IN_CURITEM(),
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001576 flags, &property ) )
1577 {
1578 if ( error && error != HB_Err_Not_Covered )
1579 return error;
1580
1581 if ( buffer->in_pos == buffer->in_length )
Behdad Esfahbode90d1992007-08-21 08:03:26 +00001582 {
1583 buffer->in_pos = first_pos;
1584 return HB_Err_Not_Covered;
1585 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001586 (buffer->in_pos)++;
Behdad Esfahbode90d1992007-08-21 08:03:26 +00001587
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001588 }
1589
1590 switch ( pp->PosFormat )
1591 {
1592 case 1:
1593 error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
1594 first_pos, index,
1595 pp->ValueFormat1, pp->ValueFormat2 );
1596 break;
1597
1598 case 2:
1599 error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
1600 pp->ValueFormat1, pp->ValueFormat2 );
1601 break;
1602
1603 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001604 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001605 }
1606
Behdad Esfahbod7341a112007-04-03 22:45:29 +00001607 /* if we don't have coverage for the second glyph don't skip it for
1608 further lookups but reset in_pos back to the first_glyph and let
1609 the caller in Do_String_Lookup increment in_pos */
1610 if ( error == HB_Err_Not_Covered )
1611 buffer->in_pos = first_pos;
1612
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001613 /* adjusting the `next' glyph */
1614
1615 if ( pp->ValueFormat2 )
1616 (buffer->in_pos)++;
1617
1618 return error;
1619}
1620
1621
1622/* LookupType 3 */
1623
1624/* CursivePosFormat1 */
1625
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001626static HB_Error Load_CursivePos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001627 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001628{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001629 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001630 HB_CursivePos* cp = &st->cursive;
1631
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001632 HB_UShort n, m, count;
1633 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001634
1635 HB_EntryExitRecord* eer;
1636
1637
1638 base_offset = FILE_Pos();
1639
1640 if ( ACCESS_Frame( 4L ) )
1641 return error;
1642
1643 cp->PosFormat = GET_UShort();
1644 new_offset = GET_UShort() + base_offset;
1645
1646 FORGET_Frame();
1647
1648 cur_offset = FILE_Pos();
1649 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001650 ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001651 return error;
1652 (void)FILE_Seek( cur_offset );
1653
1654 if ( ACCESS_Frame( 2L ) )
1655 goto Fail2;
1656
1657 count = cp->EntryExitCount = GET_UShort();
1658
1659 FORGET_Frame();
1660
1661 cp->EntryExitRecord = NULL;
1662
1663 if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )
1664 goto Fail2;
1665
1666 eer = cp->EntryExitRecord;
1667
1668 for ( n = 0; n < count; n++ )
1669 {
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001670 HB_UInt entry_offset;
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00001671
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001672 if ( ACCESS_Frame( 2L ) )
1673 return error;
1674
1675 entry_offset = new_offset = GET_UShort();
1676
1677 FORGET_Frame();
1678
1679 if ( new_offset )
1680 {
1681 new_offset += base_offset;
1682
1683 cur_offset = FILE_Pos();
1684 if ( FILE_Seek( new_offset ) ||
1685 ( error = Load_Anchor( &eer[n].EntryAnchor,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001686 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001687 goto Fail1;
1688 (void)FILE_Seek( cur_offset );
1689 }
1690 else
1691 eer[n].EntryAnchor.PosFormat = 0;
1692
1693 if ( ACCESS_Frame( 2L ) )
1694 return error;
1695
1696 new_offset = GET_UShort();
1697
1698 FORGET_Frame();
1699
1700 if ( new_offset )
1701 {
1702 new_offset += base_offset;
1703
1704 cur_offset = FILE_Pos();
1705 if ( FILE_Seek( new_offset ) ||
1706 ( error = Load_Anchor( &eer[n].ExitAnchor,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001707 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001708 {
1709 if ( entry_offset )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001710 Free_Anchor( &eer[n].EntryAnchor );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001711 goto Fail1;
1712 }
1713 (void)FILE_Seek( cur_offset );
1714 }
1715 else
1716 eer[n].ExitAnchor.PosFormat = 0;
1717 }
1718
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001719 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001720
1721Fail1:
1722 for ( m = 0; m < n; m++ )
1723 {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001724 Free_Anchor( &eer[m].EntryAnchor );
1725 Free_Anchor( &eer[m].ExitAnchor );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001726 }
1727
1728 FREE( eer );
1729
1730Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001731 _HB_OPEN_Free_Coverage( &cp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001732 return error;
1733}
1734
1735
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001736static void Free_CursivePos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001737{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001738 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001739 HB_CursivePos* cp = &st->cursive;
1740
1741 HB_EntryExitRecord* eer;
1742
1743
1744 if ( cp->EntryExitRecord )
1745 {
1746 count = cp->EntryExitCount;
1747 eer = cp->EntryExitRecord;
1748
1749 for ( n = 0; n < count; n++ )
1750 {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001751 Free_Anchor( &eer[n].EntryAnchor );
1752 Free_Anchor( &eer[n].ExitAnchor );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001753 }
1754
1755 FREE( eer );
1756 }
1757
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00001758 _HB_OPEN_Free_Coverage( &cp->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001759}
1760
1761
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001762static HB_Error Lookup_CursivePos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001763 HB_GPOS_SubTable* st,
1764 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001765 HB_UShort flags,
1766 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001767 int nesting_level )
1768{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001769 HB_UShort index, property;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001770 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001771 HB_GPOSHeader* gpos = gpi->gpos;
1772 HB_CursivePos* cp = &st->cursive;
1773
1774 HB_EntryExitRecord* eer;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00001775 HB_Fixed entry_x, entry_y;
1776 HB_Fixed exit_x, exit_y;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001777
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001778 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001779
1780 if ( context_length != 0xFFFF && context_length < 1 )
1781 {
1782 gpi->last = 0xFFFF;
1783 return HB_Err_Not_Covered;
1784 }
1785
Behdad Esfahbod30bd7632009-04-15 22:56:15 -04001786 /* Glyphs not having the right GDEF property will be ignored, i.e.,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001787 gpi->last won't be reset (contrary to user defined properties). */
1788
Behdad Esfahbodce48f032009-11-02 14:35:51 -05001789 if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001790 return error;
1791
1792 /* We don't handle mark glyphs here. According to Andrei, this isn't
1793 possible, but who knows... */
1794
Behdad Esfahbodce48f032009-11-02 14:35:51 -05001795 if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001796 {
1797 gpi->last = 0xFFFF;
1798 return HB_Err_Not_Covered;
1799 }
1800
1801 error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
1802 if ( error )
1803 {
1804 gpi->last = 0xFFFF;
1805 return error;
1806 }
1807
1808 if ( index >= cp->EntryExitCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00001809 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001810
1811 eer = &cp->EntryExitRecord[index];
1812
1813 /* Now comes the messiest part of the whole OpenType
1814 specification. At first glance, cursive connections seem easy
1815 to understand, but there are pitfalls! The reason is that
1816 the specs don't mention how to compute the advance values
1817 resp. glyph offsets. I was told it would be an omission, to
1818 be fixed in the next OpenType version... Again many thanks to
1819 Andrei Burago <andreib@microsoft.com> for clarifications.
1820
1821 Consider the following example:
1822
1823 | xadv1 |
1824 +---------+
1825 | |
1826 +-----+--+ 1 |
1827 | | .| |
1828 | 0+--+------+
1829 | 2 |
1830 | |
1831 0+--------+
1832 | xadv2 |
1833
1834 glyph1: advance width = 12
1835 anchor point = (3,1)
1836
1837 glyph2: advance width = 11
1838 anchor point = (9,4)
1839
1840 LSB is 1 for both glyphs (so the boxes drawn above are glyph
1841 bboxes). Writing direction is R2L; `0' denotes the glyph's
1842 coordinate origin.
1843
1844 Now the surprising part: The advance width of the *left* glyph
1845 (resp. of the *bottom* glyph) will be modified, no matter
1846 whether the writing direction is L2R or R2L (resp. T2B or
1847 B2T)! This assymetry is caused by the fact that the glyph's
1848 coordinate origin is always the lower left corner for all
1849 writing directions.
1850
1851 Continuing the above example, we can compute the new
1852 (horizontal) advance width of glyph2 as
1853
1854 9 - 3 = 6 ,
1855
1856 and the new vertical offset of glyph2 as
1857
1858 1 - 4 = -3 .
1859
1860
1861 Vertical writing direction is far more complicated:
1862
1863 a) Assuming that we recompute the advance height of the lower glyph:
1864
1865 --
1866 +---------+
1867 -- | |
1868 +-----+--+ 1 | yadv1
1869 | | .| |
1870 yadv2 | 0+--+------+ -- BSB1 --
1871 | 2 | -- -- y_offset
1872 | |
1873 BSB2 -- 0+--------+ --
1874 -- --
1875
1876 glyph1: advance height = 6
1877 anchor point = (3,1)
1878
1879 glyph2: advance height = 7
1880 anchor point = (9,4)
1881
1882 TSB is 1 for both glyphs; writing direction is T2B.
1883
1884
1885 BSB1 = yadv1 - (TSB1 + ymax1)
1886 BSB2 = yadv2 - (TSB2 + ymax2)
1887 y_offset = y2 - y1
1888
1889 vertical advance width of glyph2
1890 = y_offset + BSB2 - BSB1
1891 = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
1892 = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
1893 = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
1894
1895
1896 b) Assuming that we recompute the advance height of the upper glyph:
1897
1898 -- --
1899 +---------+ -- TSB1
1900 -- -- | |
1901 TSB2 -- +-----+--+ 1 | yadv1 ymax1
1902 | | .| |
1903 yadv2 | 0+--+------+ -- --
1904 ymax2 | 2 | -- y_offset
1905 | |
1906 -- 0+--------+ --
1907 --
1908
1909 glyph1: advance height = 6
1910 anchor point = (3,1)
1911
1912 glyph2: advance height = 7
1913 anchor point = (9,4)
1914
1915 TSB is 1 for both glyphs; writing direction is T2B.
1916
1917 y_offset = y2 - y1
1918
1919 vertical advance width of glyph2
1920 = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
1921 = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
1922
1923
1924 Comparing a) with b) shows that b) is easier to compute. I'll wait
1925 for a reply from Andrei to see what should really be implemented...
1926
1927 Since horizontal advance widths or vertical advance heights
1928 can be used alone but not together, no ambiguity occurs. */
1929
1930 if ( gpi->last == 0xFFFF )
1931 goto end;
1932
1933 /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor
1934 table. */
1935
1936 error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
1937 &entry_x, &entry_y );
1938 if ( error == HB_Err_Not_Covered )
1939 goto end;
1940 if ( error )
1941 return error;
1942
1943 if ( gpi->r2l )
1944 {
1945 POSITION( buffer->in_pos )->x_advance = entry_x - gpi->anchor_x;
1946 POSITION( buffer->in_pos )->new_advance = TRUE;
1947 }
1948 else
1949 {
1950 POSITION( gpi->last )->x_advance = gpi->anchor_x - entry_x;
1951 POSITION( gpi->last )->new_advance = TRUE;
1952 }
1953
1954 if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
1955 {
1956 POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
1957 POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
1958 }
1959 else
1960 {
1961 POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
1962 POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
1963 }
1964
1965end:
1966 error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
1967 &exit_x, &exit_y );
1968 if ( error == HB_Err_Not_Covered )
1969 gpi->last = 0xFFFF;
1970 else
1971 {
1972 gpi->last = buffer->in_pos;
1973 gpi->anchor_x = exit_x;
1974 gpi->anchor_y = exit_y;
1975 }
1976 if ( error )
1977 return error;
1978
1979 (buffer->in_pos)++;
1980
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001981 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001982}
1983
1984
1985/* LookupType 4 */
1986
1987/* BaseArray */
1988
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001989static HB_Error Load_BaseArray( HB_BaseArray* ba,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001990 HB_UShort num_classes,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00001991 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001992{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00001993 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001994
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00001995 HB_UShort m, n, count;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00001996 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00001997
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00001998 HB_BaseRecord *br;
1999 HB_Anchor *ban, *bans;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002000
2001
2002 base_offset = FILE_Pos();
2003
2004 if ( ACCESS_Frame( 2L ) )
2005 return error;
2006
2007 count = ba->BaseCount = GET_UShort();
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00002008
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002009 FORGET_Frame();
2010
2011 ba->BaseRecord = NULL;
2012
2013 if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )
2014 return error;
2015
2016 br = ba->BaseRecord;
2017
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002018 bans = NULL;
2019
2020 if ( ALLOC_ARRAY( bans, count * num_classes, HB_Anchor ) )
2021 goto Fail;
2022
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002023 for ( m = 0; m < count; m++ )
2024 {
2025 br[m].BaseAnchor = NULL;
2026
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002027 ban = br[m].BaseAnchor = bans + m * num_classes;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002028
2029 for ( n = 0; n < num_classes; n++ )
2030 {
2031 if ( ACCESS_Frame( 2L ) )
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002032 goto Fail;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002033
2034 new_offset = GET_UShort() + base_offset;
2035
2036 FORGET_Frame();
2037
2038 if (new_offset == base_offset) {
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002039 /* XXX
2040 * Doulos SIL Regular is buggy and has zero offsets here.
2041 * Skip it
2042 */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002043 ban[n].PosFormat = 0;
2044 continue;
2045 }
2046
2047 cur_offset = FILE_Pos();
2048 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002049 ( error = Load_Anchor( &ban[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002050 goto Fail;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002051 (void)FILE_Seek( cur_offset );
2052 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002053 }
2054
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002055 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002056
2057Fail:
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002058 FREE( bans );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002059 FREE( br );
2060 return error;
2061}
2062
2063
2064static void Free_BaseArray( HB_BaseArray* ba,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002065 HB_UShort num_classes )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002066{
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002067 HB_BaseRecord *br;
2068 HB_Anchor *bans;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002069
Behdad Esfahbod0a47c4f2009-01-29 09:19:20 +00002070 HB_UNUSED(num_classes);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002071
2072 if ( ba->BaseRecord )
2073 {
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002074 br = ba->BaseRecord;
2075
Behdad Esfahbodd49caf12009-03-02 15:16:11 +03302076 if ( ba->BaseCount )
2077 {
2078 bans = br[0].BaseAnchor;
2079 FREE( bans );
2080 }
2081
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002082 FREE( br );
2083 }
2084}
2085
2086
2087/* MarkBasePosFormat1 */
2088
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002089static HB_Error Load_MarkBasePos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002090 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002091{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002092 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002093 HB_MarkBasePos* mbp = &st->markbase;
2094
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002095 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002096
2097
2098 base_offset = FILE_Pos();
2099
2100 if ( ACCESS_Frame( 4L ) )
2101 return error;
2102
2103 mbp->PosFormat = GET_UShort();
2104 new_offset = GET_UShort() + base_offset;
2105
2106 FORGET_Frame();
2107
2108 if (mbp->PosFormat != 1)
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002109 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002110
2111 cur_offset = FILE_Pos();
2112 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002113 ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002114 return error;
2115 (void)FILE_Seek( cur_offset );
2116
2117 if ( ACCESS_Frame( 2L ) )
2118 goto Fail3;
2119
2120 new_offset = GET_UShort() + base_offset;
2121
2122 FORGET_Frame();
2123
2124 cur_offset = FILE_Pos();
2125 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002126 ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002127 goto Fail3;
2128 (void)FILE_Seek( cur_offset );
2129
2130 if ( ACCESS_Frame( 4L ) )
2131 goto Fail2;
2132
2133 mbp->ClassCount = GET_UShort();
2134 new_offset = GET_UShort() + base_offset;
2135
2136 FORGET_Frame();
2137
2138 cur_offset = FILE_Pos();
2139 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002140 ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002141 goto Fail2;
2142 (void)FILE_Seek( cur_offset );
2143
2144 if ( ACCESS_Frame( 2L ) )
2145 goto Fail1;
2146
2147 new_offset = GET_UShort() + base_offset;
2148
2149 FORGET_Frame();
2150
2151 cur_offset = FILE_Pos();
2152 if ( FILE_Seek( new_offset ) ||
2153 ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002154 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002155 goto Fail1;
2156
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002157 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002158
2159Fail1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002160 Free_MarkArray( &mbp->MarkArray );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002161
2162Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002163 _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002164
2165Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002166 _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002167 return error;
2168}
2169
2170
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002171static void Free_MarkBasePos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002172{
2173 HB_MarkBasePos* mbp = &st->markbase;
2174
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002175 Free_BaseArray( &mbp->BaseArray, mbp->ClassCount );
2176 Free_MarkArray( &mbp->MarkArray );
2177 _HB_OPEN_Free_Coverage( &mbp->BaseCoverage );
2178 _HB_OPEN_Free_Coverage( &mbp->MarkCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002179}
2180
2181
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002182static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002183 HB_GPOS_SubTable* st,
2184 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002185 HB_UShort flags,
2186 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002187 int nesting_level )
2188{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002189 HB_UShort i, j, mark_index, base_index, property, class;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00002190 HB_Fixed x_mark_value, y_mark_value, x_base_value, y_base_value;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002191 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002192 HB_GPOSHeader* gpos = gpi->gpos;
2193 HB_MarkBasePos* mbp = &st->markbase;
2194
2195 HB_MarkArray* ma;
2196 HB_BaseArray* ba;
2197 HB_BaseRecord* br;
2198 HB_Anchor* mark_anchor;
2199 HB_Anchor* base_anchor;
2200
2201 HB_Position o;
2202
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002203 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002204
2205 if ( context_length != 0xFFFF && context_length < 1 )
2206 return HB_Err_Not_Covered;
2207
2208 if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
2209 return HB_Err_Not_Covered;
2210
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002211 if ( CHECK_Property( gpos->layout, IN_CURITEM(),
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002212 flags, &property ) )
2213 return error;
2214
2215 error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
2216 &mark_index );
2217 if ( error )
2218 return error;
2219
2220 /* now we search backwards for a non-mark glyph */
2221
2222 i = 1;
2223 j = buffer->in_pos - 1;
2224
2225 while ( i <= buffer->in_pos )
2226 {
Behdad Esfahbod30bd7632009-04-15 22:56:15 -04002227 property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j));
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002228 if ( !property )
2229 return HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002230
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002231 if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002232 break;
2233
2234 i++;
2235 j--;
2236 }
2237
2238 /* The following assertion is too strong -- at least for mangal.ttf. */
2239#if 0
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002240 if ( property != HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002241 return HB_Err_Not_Covered;
2242#endif
2243
2244 if ( i > buffer->in_pos )
2245 return HB_Err_Not_Covered;
2246
2247 error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
2248 &base_index );
2249 if ( error )
2250 return error;
2251
2252 ma = &mbp->MarkArray;
2253
2254 if ( mark_index >= ma->MarkCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002255 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002256
2257 class = ma->MarkRecord[mark_index].Class;
2258 mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
2259
2260 if ( class >= mbp->ClassCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002261 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002262
2263 ba = &mbp->BaseArray;
2264
2265 if ( base_index >= ba->BaseCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002266 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002267
2268 br = &ba->BaseRecord[base_index];
2269 base_anchor = &br->BaseAnchor[class];
2270
2271 error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
2272 &x_mark_value, &y_mark_value );
2273 if ( error )
2274 return error;
2275
2276 error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
2277 &x_base_value, &y_base_value );
2278 if ( error )
2279 return error;
2280
2281 /* anchor points are not cumulative */
2282
2283 o = POSITION( buffer->in_pos );
2284
2285 o->x_pos = x_base_value - x_mark_value;
2286 o->y_pos = y_base_value - y_mark_value;
2287 o->x_advance = 0;
2288 o->y_advance = 0;
2289 o->back = i;
2290
2291 (buffer->in_pos)++;
2292
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002293 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002294}
2295
2296
2297/* LookupType 5 */
2298
2299/* LigatureAttach */
2300
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002301static HB_Error Load_LigatureAttach( HB_LigatureAttach* lat,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002302 HB_UShort num_classes,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002303 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002304{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002305 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002306
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002307 HB_UShort m, n, k, count;
2308 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002309
2310 HB_ComponentRecord* cr;
2311 HB_Anchor* lan;
2312
2313
2314 base_offset = FILE_Pos();
2315
2316 if ( ACCESS_Frame( 2L ) )
2317 return error;
2318
2319 count = lat->ComponentCount = GET_UShort();
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00002320
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002321 FORGET_Frame();
2322
2323 lat->ComponentRecord = NULL;
2324
2325 if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )
2326 return error;
2327
2328 cr = lat->ComponentRecord;
2329
2330 for ( m = 0; m < count; m++ )
2331 {
2332 cr[m].LigatureAnchor = NULL;
2333
2334 if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
2335 goto Fail;
2336
2337 lan = cr[m].LigatureAnchor;
2338
2339 for ( n = 0; n < num_classes; n++ )
2340 {
2341 if ( ACCESS_Frame( 2L ) )
2342 goto Fail0;
2343
2344 new_offset = GET_UShort();
2345
2346 FORGET_Frame();
2347
2348 if ( new_offset )
2349 {
2350 new_offset += base_offset;
2351
2352 cur_offset = FILE_Pos();
2353 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002354 ( error = Load_Anchor( &lan[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002355 goto Fail0;
2356 (void)FILE_Seek( cur_offset );
2357 }
2358 else
2359 lan[n].PosFormat = 0;
2360 }
2361
2362 continue;
2363 Fail0:
2364 for ( k = 0; k < n; k++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002365 Free_Anchor( &lan[k] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002366 goto Fail;
2367 }
2368
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002369 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002370
2371Fail:
2372 for ( k = 0; k < m; k++ )
2373 {
2374 lan = cr[k].LigatureAnchor;
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00002375
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002376 for ( n = 0; n < num_classes; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002377 Free_Anchor( &lan[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002378
2379 FREE( lan );
2380 }
2381
2382 FREE( cr );
2383 return error;
2384}
2385
2386
2387static void Free_LigatureAttach( HB_LigatureAttach* lat,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002388 HB_UShort num_classes )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002389{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002390 HB_UShort m, n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002391
2392 HB_ComponentRecord* cr;
2393 HB_Anchor* lan;
2394
2395
2396 if ( lat->ComponentRecord )
2397 {
2398 count = lat->ComponentCount;
2399 cr = lat->ComponentRecord;
2400
2401 for ( m = 0; m < count; m++ )
2402 {
2403 lan = cr[m].LigatureAnchor;
2404
2405 for ( n = 0; n < num_classes; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002406 Free_Anchor( &lan[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002407
2408 FREE( lan );
2409 }
2410
2411 FREE( cr );
2412 }
2413}
2414
2415
2416/* LigatureArray */
2417
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002418static HB_Error Load_LigatureArray( HB_LigatureArray* la,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002419 HB_UShort num_classes,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002420 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002421{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002422 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002423
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002424 HB_UShort n, m, count;
2425 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002426
2427 HB_LigatureAttach* lat;
2428
2429
2430 base_offset = FILE_Pos();
2431
2432 if ( ACCESS_Frame( 2L ) )
2433 return error;
2434
2435 count = la->LigatureCount = GET_UShort();
2436
2437 FORGET_Frame();
2438
2439 la->LigatureAttach = NULL;
2440
2441 if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )
2442 return error;
2443
2444 lat = la->LigatureAttach;
2445
2446 for ( n = 0; n < count; n++ )
2447 {
2448 if ( ACCESS_Frame( 2L ) )
2449 goto Fail;
2450
2451 new_offset = GET_UShort() + base_offset;
2452
2453 FORGET_Frame();
2454
2455 cur_offset = FILE_Pos();
2456 if ( FILE_Seek( new_offset ) ||
2457 ( error = Load_LigatureAttach( &lat[n], num_classes,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002458 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002459 goto Fail;
2460 (void)FILE_Seek( cur_offset );
2461 }
2462
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002463 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002464
2465Fail:
2466 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002467 Free_LigatureAttach( &lat[m], num_classes );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002468
2469 FREE( lat );
2470 return error;
2471}
2472
2473
2474static void Free_LigatureArray( HB_LigatureArray* la,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002475 HB_UShort num_classes )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002476{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002477 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002478
2479 HB_LigatureAttach* lat;
2480
2481
2482 if ( la->LigatureAttach )
2483 {
2484 count = la->LigatureCount;
2485 lat = la->LigatureAttach;
2486
2487 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002488 Free_LigatureAttach( &lat[n], num_classes );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002489
2490 FREE( lat );
2491 }
2492}
2493
2494
2495/* MarkLigPosFormat1 */
2496
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002497static HB_Error Load_MarkLigPos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002498 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002499{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002500 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002501 HB_MarkLigPos* mlp = &st->marklig;
2502
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002503 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002504
2505
2506 base_offset = FILE_Pos();
2507
2508 if ( ACCESS_Frame( 4L ) )
2509 return error;
2510
2511 mlp->PosFormat = GET_UShort();
2512 new_offset = GET_UShort() + base_offset;
2513
2514 FORGET_Frame();
2515
2516 cur_offset = FILE_Pos();
2517 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002518 ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002519 return error;
2520 (void)FILE_Seek( cur_offset );
2521
2522 if ( ACCESS_Frame( 2L ) )
2523 goto Fail3;
2524
2525 new_offset = GET_UShort() + base_offset;
2526
2527 FORGET_Frame();
2528
2529 cur_offset = FILE_Pos();
2530 if ( FILE_Seek( new_offset ) ||
2531 ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002532 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002533 goto Fail3;
2534 (void)FILE_Seek( cur_offset );
2535
2536 if ( ACCESS_Frame( 4L ) )
2537 goto Fail2;
2538
2539 mlp->ClassCount = GET_UShort();
2540 new_offset = GET_UShort() + base_offset;
2541
2542 FORGET_Frame();
2543
2544 cur_offset = FILE_Pos();
2545 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002546 ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002547 goto Fail2;
2548 (void)FILE_Seek( cur_offset );
2549
2550 if ( ACCESS_Frame( 2L ) )
2551 goto Fail1;
2552
2553 new_offset = GET_UShort() + base_offset;
2554
2555 FORGET_Frame();
2556
2557 cur_offset = FILE_Pos();
2558 if ( FILE_Seek( new_offset ) ||
2559 ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002560 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002561 goto Fail1;
2562
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002563 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002564
2565Fail1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002566 Free_MarkArray( &mlp->MarkArray );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002567
2568Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002569 _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002570
2571Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002572 _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002573 return error;
2574}
2575
2576
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002577static void Free_MarkLigPos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002578{
2579 HB_MarkLigPos* mlp = &st->marklig;
2580
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002581 Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount );
2582 Free_MarkArray( &mlp->MarkArray );
2583 _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage );
2584 _HB_OPEN_Free_Coverage( &mlp->MarkCoverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002585}
2586
2587
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002588static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002589 HB_GPOS_SubTable* st,
2590 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002591 HB_UShort flags,
2592 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002593 int nesting_level )
2594{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002595 HB_UShort i, j, mark_index, lig_index, property, class;
2596 HB_UShort mark_glyph;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00002597 HB_Fixed x_mark_value, y_mark_value, x_lig_value, y_lig_value;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002598 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002599 HB_GPOSHeader* gpos = gpi->gpos;
2600 HB_MarkLigPos* mlp = &st->marklig;
2601
2602 HB_MarkArray* ma;
2603 HB_LigatureArray* la;
2604 HB_LigatureAttach* lat;
2605 HB_ComponentRecord* cr;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002606 HB_UShort comp_index;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002607 HB_Anchor* mark_anchor;
2608 HB_Anchor* lig_anchor;
2609
2610 HB_Position o;
2611
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002612 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002613
2614 if ( context_length != 0xFFFF && context_length < 1 )
2615 return HB_Err_Not_Covered;
2616
2617 if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
2618 return HB_Err_Not_Covered;
2619
2620 mark_glyph = IN_CURGLYPH();
2621
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002622 if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002623 return error;
2624
2625 error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
2626 if ( error )
2627 return error;
2628
2629 /* now we search backwards for a non-mark glyph */
2630
2631 i = 1;
2632 j = buffer->in_pos - 1;
2633
2634 while ( i <= buffer->in_pos )
2635 {
Behdad Esfahbod30bd7632009-04-15 22:56:15 -04002636 property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j));
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002637 if ( !property )
2638 return HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002639
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002640 if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002641 break;
2642
2643 i++;
2644 j--;
2645 }
2646
2647 /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
2648 too strong, thus it is commented out. */
2649#if 0
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002650 if ( property != HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002651 return HB_Err_Not_Covered;
2652#endif
2653
2654 if ( i > buffer->in_pos )
2655 return HB_Err_Not_Covered;
2656
2657 error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
2658 &lig_index );
2659 if ( error )
2660 return error;
2661
2662 ma = &mlp->MarkArray;
2663
2664 if ( mark_index >= ma->MarkCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002665 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002666
2667 class = ma->MarkRecord[mark_index].Class;
2668 mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
2669
2670 if ( class >= mlp->ClassCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002671 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002672
2673 la = &mlp->LigatureArray;
2674
2675 if ( lig_index >= la->LigatureCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002676 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002677
2678 lat = &la->LigatureAttach[lig_index];
2679
2680 /* We must now check whether the ligature ID of the current mark glyph
2681 is identical to the ligature ID of the found ligature. If yes, we
2682 can directly use the component index. If not, we attach the mark
2683 glyph to the last component of the ligature. */
2684
2685 if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
2686 {
2687 comp_index = IN_COMPONENT( buffer->in_pos );
2688 if ( comp_index >= lat->ComponentCount )
2689 return HB_Err_Not_Covered;
2690 }
2691 else
2692 comp_index = lat->ComponentCount - 1;
2693
2694 cr = &lat->ComponentRecord[comp_index];
2695 lig_anchor = &cr->LigatureAnchor[class];
2696
2697 error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
2698 &x_mark_value, &y_mark_value );
2699 if ( error )
2700 return error;
2701 error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
2702 &x_lig_value, &y_lig_value );
2703 if ( error )
2704 return error;
2705
2706 /* anchor points are not cumulative */
2707
2708 o = POSITION( buffer->in_pos );
2709
2710 o->x_pos = x_lig_value - x_mark_value;
2711 o->y_pos = y_lig_value - y_mark_value;
2712 o->x_advance = 0;
2713 o->y_advance = 0;
2714 o->back = i;
2715
2716 (buffer->in_pos)++;
2717
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002718 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002719}
2720
2721
2722/* LookupType 6 */
2723
2724/* Mark2Array */
2725
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002726static HB_Error Load_Mark2Array( HB_Mark2Array* m2a,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002727 HB_UShort num_classes,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002728 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002729{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002730 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002731
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002732 HB_UShort k, m, n, count;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002733 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002734
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002735 HB_Mark2Record *m2r;
2736 HB_Anchor *m2an, *m2ans;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002737
2738
2739 base_offset = FILE_Pos();
2740
2741 if ( ACCESS_Frame( 2L ) )
2742 return error;
2743
2744 count = m2a->Mark2Count = GET_UShort();
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00002745
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002746 FORGET_Frame();
2747
2748 m2a->Mark2Record = NULL;
2749
2750 if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )
2751 return error;
2752
2753 m2r = m2a->Mark2Record;
2754
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002755 m2ans = NULL;
2756
2757 if ( ALLOC_ARRAY( m2ans, count * num_classes, HB_Anchor ) )
2758 goto Fail;
2759
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002760 for ( m = 0; m < count; m++ )
2761 {
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002762 m2an = m2r[m].Mark2Anchor = m2ans + m * num_classes;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002763
2764 for ( n = 0; n < num_classes; n++ )
2765 {
2766 if ( ACCESS_Frame( 2L ) )
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002767 goto Fail;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002768
2769 new_offset = GET_UShort() + base_offset;
2770
2771 FORGET_Frame();
2772
Behdad Esfahbod21f7d502008-10-15 03:45:29 +00002773 if (new_offset == base_offset) {
2774 /* Anchor table not provided. Skip loading.
2775 * Some versions of FreeSans hit this. */
2776 m2an[n].PosFormat = 0;
2777 continue;
2778 }
2779
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002780 cur_offset = FILE_Pos();
2781 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002782 ( error = Load_Anchor( &m2an[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002783 goto Fail;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002784 (void)FILE_Seek( cur_offset );
2785 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002786 }
2787
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002788 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002789
2790Fail:
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002791 FREE( m2ans );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002792 FREE( m2r );
2793 return error;
2794}
2795
2796
2797static void Free_Mark2Array( HB_Mark2Array* m2a,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002798 HB_UShort num_classes )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002799{
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002800 HB_Mark2Record *m2r;
2801 HB_Anchor *m2ans;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002802
Behdad Esfahbodaca4d112009-02-02 00:13:07 +00002803 HB_UNUSED(num_classes);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002804
2805 if ( m2a->Mark2Record )
2806 {
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002807 m2r = m2a->Mark2Record;
2808
Behdad Esfahbodd49caf12009-03-02 15:16:11 +03302809 if ( m2a->Mark2Count )
2810 {
2811 m2ans = m2r[0].Mark2Anchor;
2812 FREE( m2ans );
2813 }
2814
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002815 FREE( m2r );
2816 }
2817}
2818
2819
2820/* MarkMarkPosFormat1 */
2821
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002822static HB_Error Load_MarkMarkPos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002823 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002824{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002825 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002826 HB_MarkMarkPos* mmp = &st->markmark;
2827
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002828 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002829
2830
2831 base_offset = FILE_Pos();
2832
2833 if ( ACCESS_Frame( 4L ) )
2834 return error;
2835
2836 mmp->PosFormat = GET_UShort();
2837 new_offset = GET_UShort() + base_offset;
2838
2839 FORGET_Frame();
2840
2841 cur_offset = FILE_Pos();
2842 if ( FILE_Seek( new_offset ) ||
2843 ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002844 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002845 return error;
2846 (void)FILE_Seek( cur_offset );
2847
2848 if ( ACCESS_Frame( 2L ) )
2849 goto Fail3;
2850
2851 new_offset = GET_UShort() + base_offset;
2852
2853 FORGET_Frame();
2854
2855 cur_offset = FILE_Pos();
2856 if ( FILE_Seek( new_offset ) ||
2857 ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002858 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002859 goto Fail3;
2860 (void)FILE_Seek( cur_offset );
2861
2862 if ( ACCESS_Frame( 4L ) )
2863 goto Fail2;
2864
2865 mmp->ClassCount = GET_UShort();
2866 new_offset = GET_UShort() + base_offset;
2867
2868 FORGET_Frame();
2869
2870 cur_offset = FILE_Pos();
2871 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002872 ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002873 goto Fail2;
2874 (void)FILE_Seek( cur_offset );
2875
2876 if ( ACCESS_Frame( 2L ) )
2877 goto Fail1;
2878
2879 new_offset = GET_UShort() + base_offset;
2880
2881 FORGET_Frame();
2882
2883 cur_offset = FILE_Pos();
2884 if ( FILE_Seek( new_offset ) ||
2885 ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002886 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002887 goto Fail1;
2888
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002889 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002890
2891Fail1:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002892 Free_MarkArray( &mmp->Mark1Array );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002893
2894Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002895 _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002896
2897Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002898 _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002899 return error;
2900}
2901
2902
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002903static void Free_MarkMarkPos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002904{
2905 HB_MarkMarkPos* mmp = &st->markmark;
2906
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00002907 Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount );
2908 Free_MarkArray( &mmp->Mark1Array );
2909 _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage );
2910 _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002911}
2912
2913
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002914static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002915 HB_GPOS_SubTable* st,
2916 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002917 HB_UShort flags,
2918 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002919 int nesting_level )
2920{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00002921 HB_UShort i, j, mark1_index, mark2_index, property, class;
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00002922 HB_Fixed x_mark1_value, y_mark1_value,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002923 x_mark2_value, y_mark2_value;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00002924 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002925 HB_GPOSHeader* gpos = gpi->gpos;
2926 HB_MarkMarkPos* mmp = &st->markmark;
2927
2928 HB_MarkArray* ma1;
2929 HB_Mark2Array* ma2;
2930 HB_Mark2Record* m2r;
2931 HB_Anchor* mark1_anchor;
2932 HB_Anchor* mark2_anchor;
2933
2934 HB_Position o;
2935
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00002936 HB_UNUSED(nesting_level);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002937
2938 if ( context_length != 0xFFFF && context_length < 1 )
2939 return HB_Err_Not_Covered;
2940
2941 if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
2942 return HB_Err_Not_Covered;
2943
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002944 if ( CHECK_Property( gpos->layout, IN_CURITEM(),
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002945 flags, &property ) )
2946 return error;
2947
2948 error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
2949 &mark1_index );
2950 if ( error )
2951 return error;
2952
Behdad Esfahbodf8f7bd22006-05-31 07:23:02 +00002953 /* now we search backwards for a suitable mark glyph until a non-mark
2954 glyph */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002955
2956 if ( buffer->in_pos == 0 )
2957 return HB_Err_Not_Covered;
2958
Behdad Esfahbodf8f7bd22006-05-31 07:23:02 +00002959 i = 1;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002960 j = buffer->in_pos - 1;
Behdad Esfahbodf8f7bd22006-05-31 07:23:02 +00002961 while ( i <= buffer->in_pos )
2962 {
Behdad Esfahbod30bd7632009-04-15 22:56:15 -04002963 property = _hb_ot_layout_get_glyph_property (gpos->layout, IN_GLYPH(j));
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002964 if ( !property )
2965 return HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002966
Behdad Esfahbodce48f032009-11-02 14:35:51 -05002967 if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002968 return HB_Err_Not_Covered;
Behdad Esfahbodf8f7bd22006-05-31 07:23:02 +00002969
2970 if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
2971 {
2972 if ( property == (flags & 0xFF00) )
2973 break;
2974 }
2975 else
2976 break;
2977
2978 i++;
2979 j--;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002980 }
2981
2982 error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
2983 &mark2_index );
2984 if ( error )
2985 return error;
2986
2987 ma1 = &mmp->Mark1Array;
2988
2989 if ( mark1_index >= ma1->MarkCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002990 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002991
2992 class = ma1->MarkRecord[mark1_index].Class;
2993 mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
2994
2995 if ( class >= mmp->ClassCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00002996 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00002997
2998 ma2 = &mmp->Mark2Array;
2999
3000 if ( mark2_index >= ma2->Mark2Count )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00003001 return ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003002
3003 m2r = &ma2->Mark2Record[mark2_index];
3004 mark2_anchor = &m2r->Mark2Anchor[class];
3005
3006 error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
3007 &x_mark1_value, &y_mark1_value );
3008 if ( error )
3009 return error;
3010 error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
3011 &x_mark2_value, &y_mark2_value );
3012 if ( error )
3013 return error;
3014
3015 /* anchor points are not cumulative */
3016
3017 o = POSITION( buffer->in_pos );
3018
3019 o->x_pos = x_mark2_value - x_mark1_value;
3020 o->y_pos = y_mark2_value - y_mark1_value;
3021 o->x_advance = 0;
3022 o->y_advance = 0;
3023 o->back = 1;
3024
3025 (buffer->in_pos)++;
3026
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003027 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003028}
3029
3030
3031/* Do the actual positioning for a context positioning (either format
3032 7 or 8). This is only called after we've determined that the stream
3033 matches the subrule. */
3034
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003035static HB_Error Do_ContextPos( GPOS_Instance* gpi,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003036 HB_UShort GlyphCount,
3037 HB_UShort PosCount,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003038 HB_PosLookupRecord* pos,
3039 HB_Buffer buffer,
3040 int nesting_level )
3041{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003042 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003043 HB_UInt i, old_pos;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003044
3045
3046 i = 0;
3047
3048 while ( i < GlyphCount )
3049 {
3050 if ( PosCount && i == pos->SequenceIndex )
3051 {
3052 old_pos = buffer->in_pos;
3053
3054 /* Do a positioning */
3055
3056 error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
3057 GlyphCount, nesting_level );
3058
3059 if ( error )
3060 return error;
3061
3062 pos++;
3063 PosCount--;
3064 i += buffer->in_pos - old_pos;
3065 }
3066 else
3067 {
3068 i++;
3069 (buffer->in_pos)++;
3070 }
3071 }
3072
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003073 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003074}
3075
3076
3077/* LookupType 7 */
3078
3079/* PosRule */
3080
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003081static HB_Error Load_PosRule( HB_PosRule* pr,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003082 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003083{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003084 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003085
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003086 HB_UShort n, count;
3087 HB_UShort* i;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003088
3089 HB_PosLookupRecord* plr;
3090
3091
3092 if ( ACCESS_Frame( 4L ) )
3093 return error;
3094
3095 pr->GlyphCount = GET_UShort();
3096 pr->PosCount = GET_UShort();
3097
3098 FORGET_Frame();
3099
3100 pr->Input = NULL;
3101
3102 count = pr->GlyphCount - 1; /* only GlyphCount - 1 elements */
3103
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003104 if ( ALLOC_ARRAY( pr->Input, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003105 return error;
3106
3107 i = pr->Input;
3108
3109 if ( ACCESS_Frame( count * 2L ) )
3110 goto Fail2;
3111
3112 for ( n = 0; n < count; n++ )
3113 i[n] = GET_UShort();
3114
3115 FORGET_Frame();
3116
3117 pr->PosLookupRecord = NULL;
3118
3119 count = pr->PosCount;
3120
3121 if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )
3122 goto Fail2;
3123
3124 plr = pr->PosLookupRecord;
3125
3126 if ( ACCESS_Frame( count * 4L ) )
3127 goto Fail1;
3128
3129 for ( n = 0; n < count; n++ )
3130 {
3131 plr[n].SequenceIndex = GET_UShort();
3132 plr[n].LookupListIndex = GET_UShort();
3133 }
3134
3135 FORGET_Frame();
3136
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003137 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003138
3139Fail1:
3140 FREE( plr );
3141
3142Fail2:
3143 FREE( i );
3144 return error;
3145}
3146
3147
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003148static void Free_PosRule( HB_PosRule* pr )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003149{
3150 FREE( pr->PosLookupRecord );
3151 FREE( pr->Input );
3152}
3153
3154
3155/* PosRuleSet */
3156
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003157static HB_Error Load_PosRuleSet( HB_PosRuleSet* prs,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003158 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003159{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003160 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003161
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003162 HB_UShort n, m, count;
3163 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003164
3165 HB_PosRule* pr;
3166
3167
3168 base_offset = FILE_Pos();
3169
3170 if ( ACCESS_Frame( 2L ) )
3171 return error;
3172
3173 count = prs->PosRuleCount = GET_UShort();
3174
3175 FORGET_Frame();
3176
3177 prs->PosRule = NULL;
3178
3179 if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )
3180 return error;
3181
3182 pr = prs->PosRule;
3183
3184 for ( n = 0; n < count; n++ )
3185 {
3186 if ( ACCESS_Frame( 2L ) )
3187 goto Fail;
3188
3189 new_offset = GET_UShort() + base_offset;
3190
3191 FORGET_Frame();
3192
3193 cur_offset = FILE_Pos();
3194 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003195 ( error = Load_PosRule( &pr[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003196 goto Fail;
3197 (void)FILE_Seek( cur_offset );
3198 }
3199
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003200 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003201
3202Fail:
3203 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003204 Free_PosRule( &pr[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003205
3206 FREE( pr );
3207 return error;
3208}
3209
3210
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003211static void Free_PosRuleSet( HB_PosRuleSet* prs )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003212{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003213 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003214
3215 HB_PosRule* pr;
3216
3217
3218 if ( prs->PosRule )
3219 {
3220 count = prs->PosRuleCount;
3221 pr = prs->PosRule;
3222
3223 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003224 Free_PosRule( &pr[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003225
3226 FREE( pr );
3227 }
3228}
3229
3230
3231/* ContextPosFormat1 */
3232
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003233static HB_Error Load_ContextPos1( HB_ContextPosFormat1* cpf1,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003234 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003235{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003236 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003237
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003238 HB_UShort n, m, count;
3239 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003240
3241 HB_PosRuleSet* prs;
3242
3243
3244 base_offset = FILE_Pos() - 2L;
3245
3246 if ( ACCESS_Frame( 2L ) )
3247 return error;
3248
3249 new_offset = GET_UShort() + base_offset;
3250
3251 FORGET_Frame();
3252
3253 cur_offset = FILE_Pos();
3254 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003255 ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003256 return error;
3257 (void)FILE_Seek( cur_offset );
3258
3259 if ( ACCESS_Frame( 2L ) )
3260 goto Fail2;
3261
3262 count = cpf1->PosRuleSetCount = GET_UShort();
3263
3264 FORGET_Frame();
3265
3266 cpf1->PosRuleSet = NULL;
3267
3268 if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )
3269 goto Fail2;
3270
3271 prs = cpf1->PosRuleSet;
3272
3273 for ( n = 0; n < count; n++ )
3274 {
3275 if ( ACCESS_Frame( 2L ) )
3276 goto Fail1;
3277
3278 new_offset = GET_UShort() + base_offset;
3279
3280 FORGET_Frame();
3281
3282 cur_offset = FILE_Pos();
3283 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003284 ( error = Load_PosRuleSet( &prs[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003285 goto Fail1;
3286 (void)FILE_Seek( cur_offset );
3287 }
3288
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003289 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003290
3291Fail1:
3292 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003293 Free_PosRuleSet( &prs[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003294
3295 FREE( prs );
3296
3297Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003298 _HB_OPEN_Free_Coverage( &cpf1->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003299 return error;
3300}
3301
3302
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003303static void Free_ContextPos1( HB_ContextPosFormat1* cpf1 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003304{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003305 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003306
3307 HB_PosRuleSet* prs;
3308
3309
3310 if ( cpf1->PosRuleSet )
3311 {
3312 count = cpf1->PosRuleSetCount;
3313 prs = cpf1->PosRuleSet;
3314
3315 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003316 Free_PosRuleSet( &prs[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003317
3318 FREE( prs );
3319 }
3320
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003321 _HB_OPEN_Free_Coverage( &cpf1->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003322}
3323
3324
3325/* PosClassRule */
3326
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003327static HB_Error Load_PosClassRule( HB_ContextPosFormat2* cpf2,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003328 HB_PosClassRule* pcr,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003329 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003330{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003331 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003332
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003333 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003334
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003335 HB_UShort* c;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003336 HB_PosLookupRecord* plr;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003337
3338
3339 if ( ACCESS_Frame( 4L ) )
3340 return error;
3341
3342 pcr->GlyphCount = GET_UShort();
3343 pcr->PosCount = GET_UShort();
3344
3345 FORGET_Frame();
3346
3347 if ( pcr->GlyphCount > cpf2->MaxContextLength )
3348 cpf2->MaxContextLength = pcr->GlyphCount;
3349
3350 pcr->Class = NULL;
3351
3352 count = pcr->GlyphCount - 1; /* only GlyphCount - 1 elements */
3353
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003354 if ( ALLOC_ARRAY( pcr->Class, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003355 return error;
3356
3357 c = pcr->Class;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003358
3359 if ( ACCESS_Frame( count * 2L ) )
3360 goto Fail2;
3361
3362 for ( n = 0; n < count; n++ )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003363 c[n] = GET_UShort();
3364
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003365 FORGET_Frame();
3366
3367 pcr->PosLookupRecord = NULL;
3368
3369 count = pcr->PosCount;
3370
3371 if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )
3372 goto Fail2;
3373
3374 plr = pcr->PosLookupRecord;
3375
3376 if ( ACCESS_Frame( count * 4L ) )
3377 goto Fail1;
3378
3379 for ( n = 0; n < count; n++ )
3380 {
3381 plr[n].SequenceIndex = GET_UShort();
3382 plr[n].LookupListIndex = GET_UShort();
3383 }
3384
3385 FORGET_Frame();
3386
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003387 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003388
3389Fail1:
3390 FREE( plr );
3391
3392Fail2:
3393 FREE( c );
3394 return error;
3395}
3396
3397
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003398static void Free_PosClassRule( HB_PosClassRule* pcr )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003399{
3400 FREE( pcr->PosLookupRecord );
3401 FREE( pcr->Class );
3402}
3403
3404
3405/* PosClassSet */
3406
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003407static HB_Error Load_PosClassSet( HB_ContextPosFormat2* cpf2,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003408 HB_PosClassSet* pcs,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003409 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003410{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003411 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003412
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003413 HB_UShort n, m, count;
3414 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003415
3416 HB_PosClassRule* pcr;
3417
3418
3419 base_offset = FILE_Pos();
3420
3421 if ( ACCESS_Frame( 2L ) )
3422 return error;
3423
3424 count = pcs->PosClassRuleCount = GET_UShort();
3425
3426 FORGET_Frame();
3427
3428 pcs->PosClassRule = NULL;
3429
3430 if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )
3431 return error;
3432
3433 pcr = pcs->PosClassRule;
3434
3435 for ( n = 0; n < count; n++ )
3436 {
3437 if ( ACCESS_Frame( 2L ) )
3438 goto Fail;
3439
3440 new_offset = GET_UShort() + base_offset;
3441
3442 FORGET_Frame();
3443
3444 cur_offset = FILE_Pos();
3445 if ( FILE_Seek( new_offset ) ||
3446 ( error = Load_PosClassRule( cpf2, &pcr[n],
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003447 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003448 goto Fail;
3449 (void)FILE_Seek( cur_offset );
3450 }
3451
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003452 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003453
3454Fail:
3455 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003456 Free_PosClassRule( &pcr[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003457
3458 FREE( pcr );
3459 return error;
3460}
3461
3462
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003463static void Free_PosClassSet( HB_PosClassSet* pcs )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003464{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003465 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003466
3467 HB_PosClassRule* pcr;
3468
3469
3470 if ( pcs->PosClassRule )
3471 {
3472 count = pcs->PosClassRuleCount;
3473 pcr = pcs->PosClassRule;
3474
3475 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003476 Free_PosClassRule( &pcr[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003477
3478 FREE( pcr );
3479 }
3480}
3481
3482
3483/* ContextPosFormat2 */
3484
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003485static HB_Error Load_ContextPos2( HB_ContextPosFormat2* cpf2,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003486 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003487{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003488 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003489
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003490 HB_UShort n, m, count;
3491 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003492
3493 HB_PosClassSet* pcs;
3494
3495
3496 base_offset = FILE_Pos() - 2;
3497
3498 if ( ACCESS_Frame( 2L ) )
3499 return error;
3500
3501 new_offset = GET_UShort() + base_offset;
3502
3503 FORGET_Frame();
3504
3505 cur_offset = FILE_Pos();
3506 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003507 ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003508 return error;
3509 (void)FILE_Seek( cur_offset );
3510
3511 if ( ACCESS_Frame( 4L ) )
3512 goto Fail3;
3513
3514 new_offset = GET_UShort() + base_offset;
3515
3516 /* `PosClassSetCount' is the upper limit for class values, thus we
3517 read it now to make an additional safety check. */
3518
3519 count = cpf2->PosClassSetCount = GET_UShort();
3520
3521 FORGET_Frame();
3522
3523 cur_offset = FILE_Pos();
3524 if ( FILE_Seek( new_offset ) ||
3525 ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003526 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003527 goto Fail3;
3528 (void)FILE_Seek( cur_offset );
3529
3530 cpf2->PosClassSet = NULL;
3531 cpf2->MaxContextLength = 0;
3532
3533 if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )
3534 goto Fail2;
3535
3536 pcs = cpf2->PosClassSet;
3537
3538 for ( n = 0; n < count; n++ )
3539 {
3540 if ( ACCESS_Frame( 2L ) )
3541 goto Fail1;
3542
3543 new_offset = GET_UShort() + base_offset;
3544
3545 FORGET_Frame();
3546
3547 if ( new_offset != base_offset ) /* not a NULL offset */
3548 {
3549 cur_offset = FILE_Pos();
3550 if ( FILE_Seek( new_offset ) ||
3551 ( error = Load_PosClassSet( cpf2, &pcs[n],
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003552 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003553 goto Fail1;
3554 (void)FILE_Seek( cur_offset );
3555 }
3556 else
3557 {
3558 /* we create a PosClassSet table with no entries */
3559
3560 cpf2->PosClassSet[n].PosClassRuleCount = 0;
3561 cpf2->PosClassSet[n].PosClassRule = NULL;
3562 }
3563 }
3564
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003565 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003566
3567Fail1:
3568 for ( m = 0; m < n; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003569 Free_PosClassSet( &pcs[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003570
3571 FREE( pcs );
3572
3573Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003574 _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003575
3576Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003577 _HB_OPEN_Free_Coverage( &cpf2->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003578 return error;
3579}
3580
3581
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003582static void Free_ContextPos2( HB_ContextPosFormat2* cpf2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003583{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003584 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003585
3586 HB_PosClassSet* pcs;
3587
3588
3589 if ( cpf2->PosClassSet )
3590 {
3591 count = cpf2->PosClassSetCount;
3592 pcs = cpf2->PosClassSet;
3593
3594 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003595 Free_PosClassSet( &pcs[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003596
3597 FREE( pcs );
3598 }
3599
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003600 _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef );
3601 _HB_OPEN_Free_Coverage( &cpf2->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003602}
3603
3604
3605/* ContextPosFormat3 */
3606
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003607static HB_Error Load_ContextPos3( HB_ContextPosFormat3* cpf3,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003608 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003609{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003610 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003611
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003612 HB_UShort n, count;
3613 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003614
3615 HB_Coverage* c;
3616 HB_PosLookupRecord* plr;
3617
3618
3619 base_offset = FILE_Pos() - 2L;
3620
3621 if ( ACCESS_Frame( 4L ) )
3622 return error;
3623
3624 cpf3->GlyphCount = GET_UShort();
3625 cpf3->PosCount = GET_UShort();
3626
3627 FORGET_Frame();
3628
3629 cpf3->Coverage = NULL;
3630
3631 count = cpf3->GlyphCount;
3632
3633 if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )
3634 return error;
3635
3636 c = cpf3->Coverage;
3637
3638 for ( n = 0; n < count; n++ )
3639 {
3640 if ( ACCESS_Frame( 2L ) )
3641 goto Fail2;
3642
3643 new_offset = GET_UShort() + base_offset;
3644
3645 FORGET_Frame();
3646
3647 cur_offset = FILE_Pos();
3648 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003649 ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003650 goto Fail2;
3651 (void)FILE_Seek( cur_offset );
3652 }
3653
3654 cpf3->PosLookupRecord = NULL;
3655
3656 count = cpf3->PosCount;
3657
3658 if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
3659 goto Fail2;
3660
3661 plr = cpf3->PosLookupRecord;
3662
3663 if ( ACCESS_Frame( count * 4L ) )
3664 goto Fail1;
3665
3666 for ( n = 0; n < count; n++ )
3667 {
3668 plr[n].SequenceIndex = GET_UShort();
3669 plr[n].LookupListIndex = GET_UShort();
3670 }
3671
3672 FORGET_Frame();
3673
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003674 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003675
3676Fail1:
3677 FREE( plr );
3678
3679Fail2:
3680 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003681 _HB_OPEN_Free_Coverage( &c[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003682
3683 FREE( c );
3684 return error;
3685}
3686
3687
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003688static void Free_ContextPos3( HB_ContextPosFormat3* cpf3 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003689{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003690 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003691
3692 HB_Coverage* c;
3693
3694
3695 FREE( cpf3->PosLookupRecord );
3696
3697 if ( cpf3->Coverage )
3698 {
3699 count = cpf3->GlyphCount;
3700 c = cpf3->Coverage;
3701
3702 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003703 _HB_OPEN_Free_Coverage( &c[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003704
3705 FREE( c );
3706 }
3707}
3708
3709
3710/* ContextPos */
3711
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003712static HB_Error Load_ContextPos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00003713 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003714{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003715 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003716 HB_ContextPos* cp = &st->context;
3717
3718
3719 if ( ACCESS_Frame( 2L ) )
3720 return error;
3721
3722 cp->PosFormat = GET_UShort();
3723
3724 FORGET_Frame();
3725
3726 switch ( cp->PosFormat )
3727 {
3728 case 1:
3729 return Load_ContextPos1( &cp->cpf.cpf1, stream );
3730
3731 case 2:
3732 return Load_ContextPos2( &cp->cpf.cpf2, stream );
3733
3734 case 3:
3735 return Load_ContextPos3( &cp->cpf.cpf3, stream );
3736
3737 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00003738 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003739 }
3740
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003741 return HB_Err_Ok; /* never reached */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003742}
3743
3744
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003745static void Free_ContextPos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003746{
3747 HB_ContextPos* cp = &st->context;
3748
3749 switch ( cp->PosFormat )
3750 {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00003751 case 1: Free_ContextPos1( &cp->cpf.cpf1 ); break;
3752 case 2: Free_ContextPos2( &cp->cpf.cpf2 ); break;
3753 case 3: Free_ContextPos3( &cp->cpf.cpf3 ); break;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003754 default: break;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003755 }
3756}
3757
3758
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003759static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003760 HB_ContextPosFormat1* cpf1,
3761 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003762 HB_UShort flags,
3763 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003764 int nesting_level )
3765{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003766 HB_UShort index, property;
3767 HB_UShort i, j, k, numpr;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003768 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003769 HB_GPOSHeader* gpos = gpi->gpos;
3770
3771 HB_PosRule* pr;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003772 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003773
3774
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003775 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003776
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003777 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003778 return error;
3779
3780 error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
3781 if ( error )
3782 return error;
3783
3784 pr = cpf1->PosRuleSet[index].PosRule;
3785 numpr = cpf1->PosRuleSet[index].PosRuleCount;
3786
3787 for ( k = 0; k < numpr; k++ )
3788 {
3789 if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
3790 goto next_posrule;
3791
3792 if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
3793 goto next_posrule; /* context is too long */
3794
3795 for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
3796 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003797 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003798 {
3799 if ( error && error != HB_Err_Not_Covered )
3800 return error;
3801
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003802 if ( j + pr[k].GlyphCount - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003803 goto next_posrule;
3804 j++;
3805 }
3806
3807 if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
3808 goto next_posrule;
3809 }
3810
3811 return Do_ContextPos( gpi, pr[k].GlyphCount,
3812 pr[k].PosCount, pr[k].PosLookupRecord,
3813 buffer,
3814 nesting_level );
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00003815
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003816 next_posrule:
3817 ;
3818 }
3819
3820 return HB_Err_Not_Covered;
3821}
3822
3823
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003824static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003825 HB_ContextPosFormat2* cpf2,
3826 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003827 HB_UShort flags,
3828 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003829 int nesting_level )
3830{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003831 HB_UShort index, property;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003832 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003833 HB_UShort i, j, k, known_classes;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003834
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003835 HB_UShort* classes;
3836 HB_UShort* cl;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003837 HB_GPOSHeader* gpos = gpi->gpos;
3838
3839 HB_PosClassSet* pcs;
3840 HB_PosClassRule* pr;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003841 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003842
3843
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003844 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003845
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003846 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003847 return error;
3848
3849 /* Note: The coverage table in format 2 doesn't give an index into
3850 anything. It just lets us know whether or not we need to
3851 do any lookup at all. */
3852
3853 error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
3854 if ( error )
3855 return error;
3856
Behdad Esfahbodd49caf12009-03-02 15:16:11 +03303857 if (cpf2->MaxContextLength < 1)
3858 return HB_Err_Not_Covered;
3859
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003860 if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003861 return error;
3862
3863 error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
3864 &classes[0], NULL );
3865 if ( error && error != HB_Err_Not_Covered )
3866 goto End;
3867 known_classes = 0;
3868
3869 pcs = &cpf2->PosClassSet[classes[0]];
3870 if ( !pcs )
3871 {
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00003872 error = ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003873 goto End;
3874 }
3875
3876 for ( k = 0; k < pcs->PosClassRuleCount; k++ )
3877 {
3878 pr = &pcs->PosClassRule[k];
3879
3880 if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
3881 goto next_posclassrule;
3882
3883 if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
3884 goto next_posclassrule; /* context is too long */
3885
3886 cl = pr->Class;
3887
3888 /* Start at 1 because [0] is implied */
3889
3890 for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
3891 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003892 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003893 {
3894 if ( error && error != HB_Err_Not_Covered )
3895 goto End;
3896
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003897 if ( j + pr->GlyphCount - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003898 goto next_posclassrule;
3899 j++;
3900 }
3901
3902 if ( i > known_classes )
3903 {
3904 /* Keeps us from having to do this for each rule */
3905
3906 error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
3907 if ( error && error != HB_Err_Not_Covered )
3908 goto End;
3909 known_classes = i;
3910 }
3911
3912 if ( cl[i - 1] != classes[i] )
3913 goto next_posclassrule;
3914 }
3915
3916 error = Do_ContextPos( gpi, pr->GlyphCount,
3917 pr->PosCount, pr->PosLookupRecord,
3918 buffer,
3919 nesting_level );
3920 goto End;
3921
3922 next_posclassrule:
3923 ;
3924 }
3925
3926 error = HB_Err_Not_Covered;
3927
3928End:
3929 FREE( classes );
3930 return error;
3931}
3932
3933
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003934static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003935 HB_ContextPosFormat3* cpf3,
3936 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003937 HB_UShort flags,
3938 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003939 int nesting_level )
3940{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003941 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003942 HB_UShort index, i, j, property;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003943 HB_GPOSHeader* gpos = gpi->gpos;
3944
3945 HB_Coverage* c;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003946 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003947
3948
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003949 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003950
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003951 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003952 return error;
3953
3954 if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
3955 return HB_Err_Not_Covered;
3956
3957 if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
3958 return HB_Err_Not_Covered; /* context is too long */
3959
3960 c = cpf3->Coverage;
3961
3962 for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
3963 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05003964 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003965 {
3966 if ( error && error != HB_Err_Not_Covered )
3967 return error;
3968
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003969 if ( j + cpf3->GlyphCount - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003970 return HB_Err_Not_Covered;
3971 j++;
3972 }
3973
3974 error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
3975 if ( error )
3976 return error;
3977 }
3978
3979 return Do_ContextPos( gpi, cpf3->GlyphCount,
3980 cpf3->PosCount, cpf3->PosLookupRecord,
3981 buffer,
3982 nesting_level );
3983}
3984
3985
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00003986static HB_Error Lookup_ContextPos( GPOS_Instance* gpi,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003987 HB_GPOS_SubTable* st,
3988 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00003989 HB_UShort flags,
3990 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00003991 int nesting_level )
3992{
3993 HB_ContextPos* cp = &st->context;
3994
3995 switch ( cp->PosFormat )
3996 {
3997 case 1:
3998 return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
3999 flags, context_length, nesting_level );
4000
4001 case 2:
4002 return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
4003 flags, context_length, nesting_level );
4004
4005 case 3:
4006 return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
4007 flags, context_length, nesting_level );
4008
4009 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00004010 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004011 }
4012
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004013 return HB_Err_Ok; /* never reached */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004014}
4015
4016
4017/* LookupType 8 */
4018
4019/* ChainPosRule */
4020
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004021static HB_Error Load_ChainPosRule( HB_ChainPosRule* cpr,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004022 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004023{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004024 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004025
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004026 HB_UShort n, count;
4027 HB_UShort* b;
4028 HB_UShort* i;
4029 HB_UShort* l;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004030
4031 HB_PosLookupRecord* plr;
4032
4033
4034 if ( ACCESS_Frame( 2L ) )
4035 return error;
4036
4037 cpr->BacktrackGlyphCount = GET_UShort();
4038
4039 FORGET_Frame();
4040
4041 cpr->Backtrack = NULL;
4042
4043 count = cpr->BacktrackGlyphCount;
4044
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004045 if ( ALLOC_ARRAY( cpr->Backtrack, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004046 return error;
4047
4048 b = cpr->Backtrack;
4049
4050 if ( ACCESS_Frame( count * 2L ) )
4051 goto Fail4;
4052
4053 for ( n = 0; n < count; n++ )
4054 b[n] = GET_UShort();
4055
4056 FORGET_Frame();
4057
4058 if ( ACCESS_Frame( 2L ) )
4059 goto Fail4;
4060
4061 cpr->InputGlyphCount = GET_UShort();
4062
4063 FORGET_Frame();
4064
4065 cpr->Input = NULL;
4066
4067 count = cpr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
4068
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004069 if ( ALLOC_ARRAY( cpr->Input, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004070 goto Fail4;
4071
4072 i = cpr->Input;
4073
4074 if ( ACCESS_Frame( count * 2L ) )
4075 goto Fail3;
4076
4077 for ( n = 0; n < count; n++ )
4078 i[n] = GET_UShort();
4079
4080 FORGET_Frame();
4081
4082 if ( ACCESS_Frame( 2L ) )
4083 goto Fail3;
4084
4085 cpr->LookaheadGlyphCount = GET_UShort();
4086
4087 FORGET_Frame();
4088
4089 cpr->Lookahead = NULL;
4090
4091 count = cpr->LookaheadGlyphCount;
4092
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004093 if ( ALLOC_ARRAY( cpr->Lookahead, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004094 goto Fail3;
4095
4096 l = cpr->Lookahead;
4097
4098 if ( ACCESS_Frame( count * 2L ) )
4099 goto Fail2;
4100
4101 for ( n = 0; n < count; n++ )
4102 l[n] = GET_UShort();
4103
4104 FORGET_Frame();
4105
4106 if ( ACCESS_Frame( 2L ) )
4107 goto Fail2;
4108
4109 cpr->PosCount = GET_UShort();
4110
4111 FORGET_Frame();
4112
4113 cpr->PosLookupRecord = NULL;
4114
4115 count = cpr->PosCount;
4116
4117 if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )
4118 goto Fail2;
4119
4120 plr = cpr->PosLookupRecord;
4121
4122 if ( ACCESS_Frame( count * 4L ) )
4123 goto Fail1;
4124
4125 for ( n = 0; n < count; n++ )
4126 {
4127 plr[n].SequenceIndex = GET_UShort();
4128 plr[n].LookupListIndex = GET_UShort();
4129 }
4130
4131 FORGET_Frame();
4132
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004133 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004134
4135Fail1:
4136 FREE( plr );
4137
4138Fail2:
4139 FREE( l );
4140
4141Fail3:
4142 FREE( i );
4143
4144Fail4:
4145 FREE( b );
4146 return error;
4147}
4148
4149
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004150static void Free_ChainPosRule( HB_ChainPosRule* cpr )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004151{
4152 FREE( cpr->PosLookupRecord );
4153 FREE( cpr->Lookahead );
4154 FREE( cpr->Input );
4155 FREE( cpr->Backtrack );
4156}
4157
4158
4159/* ChainPosRuleSet */
4160
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004161static HB_Error Load_ChainPosRuleSet( HB_ChainPosRuleSet* cprs,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004162 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004163{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004164 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004165
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004166 HB_UShort n, m, count;
4167 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004168
4169 HB_ChainPosRule* cpr;
4170
4171
4172 base_offset = FILE_Pos();
4173
4174 if ( ACCESS_Frame( 2L ) )
4175 return error;
4176
4177 count = cprs->ChainPosRuleCount = GET_UShort();
4178
4179 FORGET_Frame();
4180
4181 cprs->ChainPosRule = NULL;
4182
4183 if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )
4184 return error;
4185
4186 cpr = cprs->ChainPosRule;
4187
4188 for ( n = 0; n < count; n++ )
4189 {
4190 if ( ACCESS_Frame( 2L ) )
4191 goto Fail;
4192
4193 new_offset = GET_UShort() + base_offset;
4194
4195 FORGET_Frame();
4196
4197 cur_offset = FILE_Pos();
4198 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004199 ( error = Load_ChainPosRule( &cpr[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004200 goto Fail;
4201 (void)FILE_Seek( cur_offset );
4202 }
4203
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004204 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004205
4206Fail:
4207 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004208 Free_ChainPosRule( &cpr[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004209
4210 FREE( cpr );
4211 return error;
4212}
4213
4214
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004215static void Free_ChainPosRuleSet( HB_ChainPosRuleSet* cprs )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004216{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004217 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004218
4219 HB_ChainPosRule* cpr;
4220
4221
4222 if ( cprs->ChainPosRule )
4223 {
4224 count = cprs->ChainPosRuleCount;
4225 cpr = cprs->ChainPosRule;
4226
4227 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004228 Free_ChainPosRule( &cpr[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004229
4230 FREE( cpr );
4231 }
4232}
4233
4234
4235/* ChainContextPosFormat1 */
4236
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004237static HB_Error Load_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004238 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004239{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004240 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004241
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004242 HB_UShort n, m, count;
4243 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004244
4245 HB_ChainPosRuleSet* cprs;
4246
4247
4248 base_offset = FILE_Pos() - 2L;
4249
4250 if ( ACCESS_Frame( 2L ) )
4251 return error;
4252
4253 new_offset = GET_UShort() + base_offset;
4254
4255 FORGET_Frame();
4256
4257 cur_offset = FILE_Pos();
4258 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004259 ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004260 return error;
4261 (void)FILE_Seek( cur_offset );
4262
4263 if ( ACCESS_Frame( 2L ) )
4264 goto Fail2;
4265
4266 count = ccpf1->ChainPosRuleSetCount = GET_UShort();
4267
4268 FORGET_Frame();
4269
4270 ccpf1->ChainPosRuleSet = NULL;
4271
4272 if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )
4273 goto Fail2;
4274
4275 cprs = ccpf1->ChainPosRuleSet;
4276
4277 for ( n = 0; n < count; n++ )
4278 {
4279 if ( ACCESS_Frame( 2L ) )
4280 goto Fail1;
4281
4282 new_offset = GET_UShort() + base_offset;
4283
4284 FORGET_Frame();
4285
4286 cur_offset = FILE_Pos();
4287 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004288 ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004289 goto Fail1;
4290 (void)FILE_Seek( cur_offset );
4291 }
4292
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004293 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004294
4295Fail1:
4296 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004297 Free_ChainPosRuleSet( &cprs[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004298
4299 FREE( cprs );
4300
4301Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004302 _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004303 return error;
4304}
4305
4306
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004307static void Free_ChainContextPos1( HB_ChainContextPosFormat1* ccpf1 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004308{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004309 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004310
4311 HB_ChainPosRuleSet* cprs;
4312
4313
4314 if ( ccpf1->ChainPosRuleSet )
4315 {
4316 count = ccpf1->ChainPosRuleSetCount;
4317 cprs = ccpf1->ChainPosRuleSet;
4318
4319 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004320 Free_ChainPosRuleSet( &cprs[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004321
4322 FREE( cprs );
4323 }
4324
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004325 _HB_OPEN_Free_Coverage( &ccpf1->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004326}
4327
4328
4329/* ChainPosClassRule */
4330
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004331static HB_Error Load_ChainPosClassRule(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004332 HB_ChainContextPosFormat2* ccpf2,
4333 HB_ChainPosClassRule* cpcr,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004334 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004335{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004336 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004337
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004338 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004339
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004340 HB_UShort* b;
4341 HB_UShort* i;
4342 HB_UShort* l;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004343 HB_PosLookupRecord* plr;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004344
4345
4346 if ( ACCESS_Frame( 2L ) )
4347 return error;
4348
4349 cpcr->BacktrackGlyphCount = GET_UShort();
4350
4351 FORGET_Frame();
4352
4353 if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
4354 ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
4355
4356 cpcr->Backtrack = NULL;
4357
4358 count = cpcr->BacktrackGlyphCount;
4359
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004360 if ( ALLOC_ARRAY( cpcr->Backtrack, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004361 return error;
4362
4363 b = cpcr->Backtrack;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004364
4365 if ( ACCESS_Frame( count * 2L ) )
4366 goto Fail4;
4367
4368 for ( n = 0; n < count; n++ )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004369 b[n] = GET_UShort();
4370
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004371 FORGET_Frame();
4372
4373 if ( ACCESS_Frame( 2L ) )
4374 goto Fail4;
4375
4376 cpcr->InputGlyphCount = GET_UShort();
4377
4378 if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
4379 ccpf2->MaxInputLength = cpcr->InputGlyphCount;
4380
4381 FORGET_Frame();
4382
4383 cpcr->Input = NULL;
4384
4385 count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
4386
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004387 if ( ALLOC_ARRAY( cpcr->Input, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004388 goto Fail4;
4389
4390 i = cpcr->Input;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004391
4392 if ( ACCESS_Frame( count * 2L ) )
4393 goto Fail3;
4394
4395 for ( n = 0; n < count; n++ )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004396 i[n] = GET_UShort();
4397
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004398 FORGET_Frame();
4399
4400 if ( ACCESS_Frame( 2L ) )
4401 goto Fail3;
4402
4403 cpcr->LookaheadGlyphCount = GET_UShort();
4404
4405 FORGET_Frame();
4406
4407 if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
4408 ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
4409
4410 cpcr->Lookahead = NULL;
4411
4412 count = cpcr->LookaheadGlyphCount;
4413
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004414 if ( ALLOC_ARRAY( cpcr->Lookahead, count, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004415 goto Fail3;
4416
4417 l = cpcr->Lookahead;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004418
4419 if ( ACCESS_Frame( count * 2L ) )
4420 goto Fail2;
4421
4422 for ( n = 0; n < count; n++ )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004423 l[n] = GET_UShort();
4424
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004425 FORGET_Frame();
4426
4427 if ( ACCESS_Frame( 2L ) )
4428 goto Fail2;
4429
4430 cpcr->PosCount = GET_UShort();
4431
4432 FORGET_Frame();
4433
4434 cpcr->PosLookupRecord = NULL;
4435
4436 count = cpcr->PosCount;
4437
4438 if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )
4439 goto Fail2;
4440
4441 plr = cpcr->PosLookupRecord;
4442
4443 if ( ACCESS_Frame( count * 4L ) )
4444 goto Fail1;
4445
4446 for ( n = 0; n < count; n++ )
4447 {
4448 plr[n].SequenceIndex = GET_UShort();
4449 plr[n].LookupListIndex = GET_UShort();
4450 }
4451
4452 FORGET_Frame();
4453
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004454 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004455
4456Fail1:
4457 FREE( plr );
4458
4459Fail2:
4460 FREE( l );
4461
4462Fail3:
4463 FREE( i );
4464
4465Fail4:
4466 FREE( b );
4467 return error;
4468}
4469
4470
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004471static void Free_ChainPosClassRule( HB_ChainPosClassRule* cpcr )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004472{
4473 FREE( cpcr->PosLookupRecord );
4474 FREE( cpcr->Lookahead );
4475 FREE( cpcr->Input );
4476 FREE( cpcr->Backtrack );
4477}
4478
4479
4480/* PosClassSet */
4481
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004482static HB_Error Load_ChainPosClassSet(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004483 HB_ChainContextPosFormat2* ccpf2,
4484 HB_ChainPosClassSet* cpcs,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004485 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004486{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004487 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004488
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004489 HB_UShort n, m, count;
4490 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004491
4492 HB_ChainPosClassRule* cpcr;
4493
4494
4495 base_offset = FILE_Pos();
4496
4497 if ( ACCESS_Frame( 2L ) )
4498 return error;
4499
4500 count = cpcs->ChainPosClassRuleCount = GET_UShort();
4501
4502 FORGET_Frame();
4503
4504 cpcs->ChainPosClassRule = NULL;
4505
4506 if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
4507 HB_ChainPosClassRule ) )
4508 return error;
4509
4510 cpcr = cpcs->ChainPosClassRule;
4511
4512 for ( n = 0; n < count; n++ )
4513 {
4514 if ( ACCESS_Frame( 2L ) )
4515 goto Fail;
4516
4517 new_offset = GET_UShort() + base_offset;
4518
4519 FORGET_Frame();
4520
4521 cur_offset = FILE_Pos();
4522 if ( FILE_Seek( new_offset ) ||
4523 ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004524 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004525 goto Fail;
4526 (void)FILE_Seek( cur_offset );
4527 }
4528
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004529 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004530
4531Fail:
4532 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004533 Free_ChainPosClassRule( &cpcr[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004534
4535 FREE( cpcr );
4536 return error;
4537}
4538
4539
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004540static void Free_ChainPosClassSet( HB_ChainPosClassSet* cpcs )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004541{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004542 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004543
4544 HB_ChainPosClassRule* cpcr;
4545
4546
4547 if ( cpcs->ChainPosClassRule )
4548 {
4549 count = cpcs->ChainPosClassRuleCount;
4550 cpcr = cpcs->ChainPosClassRule;
4551
4552 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004553 Free_ChainPosClassRule( &cpcr[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004554
4555 FREE( cpcr );
4556 }
4557}
4558
4559
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004560/* ChainContextPosFormat2 */
4561
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004562static HB_Error Load_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004563 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004564{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004565 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004566
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004567 HB_UShort n, m, count;
4568 HB_UInt cur_offset, new_offset, base_offset;
4569 HB_UInt backtrack_offset, input_offset, lookahead_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004570
4571 HB_ChainPosClassSet* cpcs;
4572
4573
4574 base_offset = FILE_Pos() - 2;
4575
4576 if ( ACCESS_Frame( 2L ) )
4577 return error;
4578
4579 new_offset = GET_UShort() + base_offset;
4580
4581 FORGET_Frame();
4582
4583 cur_offset = FILE_Pos();
4584 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004585 ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004586 return error;
4587 (void)FILE_Seek( cur_offset );
4588
4589 if ( ACCESS_Frame( 8L ) )
4590 goto Fail5;
4591
4592 backtrack_offset = GET_UShort();
4593 input_offset = GET_UShort();
4594 lookahead_offset = GET_UShort();
4595
4596 /* `ChainPosClassSetCount' is the upper limit for input class values,
4597 thus we read it now to make an additional safety check. No limit
4598 is known or needed for the other two class definitions */
4599
4600 count = ccpf2->ChainPosClassSetCount = GET_UShort();
4601
4602 FORGET_Frame();
4603
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004604 if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00004605 backtrack_offset, base_offset,
4606 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004607 goto Fail5;
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004608 if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00004609 input_offset, base_offset,
4610 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004611 goto Fail4;
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004612 if ( ( error = _HB_OPEN_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00004613 lookahead_offset, base_offset,
4614 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004615 goto Fail3;
4616
4617 ccpf2->ChainPosClassSet = NULL;
4618 ccpf2->MaxBacktrackLength = 0;
4619 ccpf2->MaxInputLength = 0;
4620 ccpf2->MaxLookaheadLength = 0;
4621
4622 if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )
4623 goto Fail2;
4624
4625 cpcs = ccpf2->ChainPosClassSet;
4626
4627 for ( n = 0; n < count; n++ )
4628 {
4629 if ( ACCESS_Frame( 2L ) )
4630 goto Fail1;
4631
4632 new_offset = GET_UShort() + base_offset;
4633
4634 FORGET_Frame();
4635
4636 if ( new_offset != base_offset ) /* not a NULL offset */
4637 {
4638 cur_offset = FILE_Pos();
4639 if ( FILE_Seek( new_offset ) ||
4640 ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004641 stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004642 goto Fail1;
4643 (void)FILE_Seek( cur_offset );
4644 }
4645 else
4646 {
4647 /* we create a ChainPosClassSet table with no entries */
4648
4649 ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
4650 ccpf2->ChainPosClassSet[n].ChainPosClassRule = NULL;
4651 }
4652 }
4653
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004654 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004655
4656Fail1:
4657 for ( m = 0; m < n; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004658 Free_ChainPosClassSet( &cpcs[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004659
4660 FREE( cpcs );
4661
4662Fail2:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004663 _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004664
4665Fail3:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004666 _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004667
4668Fail4:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004669 _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004670
4671Fail5:
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004672 _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004673 return error;
4674}
4675
4676
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004677static void Free_ChainContextPos2( HB_ChainContextPosFormat2* ccpf2 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004678{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004679 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004680
4681 HB_ChainPosClassSet* cpcs;
4682
4683
4684 if ( ccpf2->ChainPosClassSet )
4685 {
4686 count = ccpf2->ChainPosClassSetCount;
4687 cpcs = ccpf2->ChainPosClassSet;
4688
4689 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004690 Free_ChainPosClassSet( &cpcs[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004691
4692 FREE( cpcs );
4693 }
4694
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004695 _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef );
4696 _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef );
4697 _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004698
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004699 _HB_OPEN_Free_Coverage( &ccpf2->Coverage );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004700}
4701
4702
4703/* ChainContextPosFormat3 */
4704
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004705static HB_Error Load_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004706 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004707{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004708 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004709
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004710 HB_UShort n, nb, ni, nl, m, count;
4711 HB_UShort backtrack_count, input_count, lookahead_count;
4712 HB_UInt cur_offset, new_offset, base_offset;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004713
4714 HB_Coverage* b;
4715 HB_Coverage* i;
4716 HB_Coverage* l;
4717 HB_PosLookupRecord* plr;
4718
4719
4720 base_offset = FILE_Pos() - 2L;
4721
4722 if ( ACCESS_Frame( 2L ) )
4723 return error;
4724
4725 ccpf3->BacktrackGlyphCount = GET_UShort();
4726
4727 FORGET_Frame();
4728
4729 ccpf3->BacktrackCoverage = NULL;
4730
4731 backtrack_count = ccpf3->BacktrackGlyphCount;
4732
4733 if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
4734 HB_Coverage ) )
4735 return error;
4736
4737 b = ccpf3->BacktrackCoverage;
4738
4739 for ( nb = 0; nb < backtrack_count; nb++ )
4740 {
4741 if ( ACCESS_Frame( 2L ) )
4742 goto Fail4;
4743
4744 new_offset = GET_UShort() + base_offset;
4745
4746 FORGET_Frame();
4747
4748 cur_offset = FILE_Pos();
4749 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004750 ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004751 goto Fail4;
4752 (void)FILE_Seek( cur_offset );
4753 }
4754
4755 if ( ACCESS_Frame( 2L ) )
4756 goto Fail4;
4757
4758 ccpf3->InputGlyphCount = GET_UShort();
4759
4760 FORGET_Frame();
4761
4762 ccpf3->InputCoverage = NULL;
4763
4764 input_count = ccpf3->InputGlyphCount;
4765
4766 if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )
4767 goto Fail4;
4768
4769 i = ccpf3->InputCoverage;
4770
4771 for ( ni = 0; ni < input_count; ni++ )
4772 {
4773 if ( ACCESS_Frame( 2L ) )
4774 goto Fail3;
4775
4776 new_offset = GET_UShort() + base_offset;
4777
4778 FORGET_Frame();
4779
4780 cur_offset = FILE_Pos();
4781 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004782 ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004783 goto Fail3;
4784 (void)FILE_Seek( cur_offset );
4785 }
4786
4787 if ( ACCESS_Frame( 2L ) )
4788 goto Fail3;
4789
4790 ccpf3->LookaheadGlyphCount = GET_UShort();
4791
4792 FORGET_Frame();
4793
4794 ccpf3->LookaheadCoverage = NULL;
4795
4796 lookahead_count = ccpf3->LookaheadGlyphCount;
4797
4798 if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
4799 HB_Coverage ) )
4800 goto Fail3;
4801
4802 l = ccpf3->LookaheadCoverage;
4803
4804 for ( nl = 0; nl < lookahead_count; nl++ )
4805 {
4806 if ( ACCESS_Frame( 2L ) )
4807 goto Fail2;
4808
4809 new_offset = GET_UShort() + base_offset;
4810
4811 FORGET_Frame();
4812
4813 cur_offset = FILE_Pos();
4814 if ( FILE_Seek( new_offset ) ||
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004815 ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != HB_Err_Ok )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004816 goto Fail2;
4817 (void)FILE_Seek( cur_offset );
4818 }
4819
4820 if ( ACCESS_Frame( 2L ) )
4821 goto Fail2;
4822
4823 ccpf3->PosCount = GET_UShort();
4824
4825 FORGET_Frame();
4826
4827 ccpf3->PosLookupRecord = NULL;
4828
4829 count = ccpf3->PosCount;
4830
4831 if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
4832 goto Fail2;
4833
4834 plr = ccpf3->PosLookupRecord;
4835
4836 if ( ACCESS_Frame( count * 4L ) )
4837 goto Fail1;
4838
4839 for ( n = 0; n < count; n++ )
4840 {
4841 plr[n].SequenceIndex = GET_UShort();
4842 plr[n].LookupListIndex = GET_UShort();
4843 }
4844
4845 FORGET_Frame();
4846
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004847 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004848
4849Fail1:
4850 FREE( plr );
4851
4852Fail2:
Behdad Esfahbodd2a61312006-04-12 18:47:50 +00004853 for ( m = 0; m < nl; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004854 _HB_OPEN_Free_Coverage( &l[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004855
4856 FREE( l );
4857
4858Fail3:
Behdad Esfahbodd2a61312006-04-12 18:47:50 +00004859 for ( m = 0; m < ni; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004860 _HB_OPEN_Free_Coverage( &i[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004861
4862 FREE( i );
4863
4864Fail4:
Behdad Esfahbodd2a61312006-04-12 18:47:50 +00004865 for ( m = 0; m < nb; m++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004866 _HB_OPEN_Free_Coverage( &b[m] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004867
4868 FREE( b );
4869 return error;
4870}
4871
4872
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004873static void Free_ChainContextPos3( HB_ChainContextPosFormat3* ccpf3 )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004874{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004875 HB_UShort n, count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004876
4877 HB_Coverage* c;
4878
4879
4880 FREE( ccpf3->PosLookupRecord );
4881
4882 if ( ccpf3->LookaheadCoverage )
4883 {
4884 count = ccpf3->LookaheadGlyphCount;
4885 c = ccpf3->LookaheadCoverage;
4886
4887 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004888 _HB_OPEN_Free_Coverage( &c[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004889
4890 FREE( c );
4891 }
4892
4893 if ( ccpf3->InputCoverage )
4894 {
4895 count = ccpf3->InputGlyphCount;
4896 c = ccpf3->InputCoverage;
4897
4898 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004899 _HB_OPEN_Free_Coverage( &c[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004900
4901 FREE( c );
4902 }
4903
4904 if ( ccpf3->BacktrackCoverage )
4905 {
4906 count = ccpf3->BacktrackGlyphCount;
4907 c = ccpf3->BacktrackCoverage;
4908
4909 for ( n = 0; n < count; n++ )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004910 _HB_OPEN_Free_Coverage( &c[n] );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004911
4912 FREE( c );
4913 }
4914}
4915
4916
4917/* ChainContextPos */
4918
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004919static HB_Error Load_ChainContextPos( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00004920 HB_Stream stream )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004921{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004922 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004923 HB_ChainContextPos* ccp = &st->chain;
4924
4925
4926 if ( ACCESS_Frame( 2L ) )
4927 return error;
4928
4929 ccp->PosFormat = GET_UShort();
4930
4931 FORGET_Frame();
4932
4933 switch ( ccp->PosFormat )
4934 {
4935 case 1:
4936 return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
4937
4938 case 2:
4939 return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
4940
4941 case 3:
4942 return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
4943
4944 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00004945 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004946 }
4947
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004948 return HB_Err_Ok; /* never reached */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004949}
4950
4951
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004952static void Free_ChainContextPos( HB_GPOS_SubTable* st )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004953{
4954 HB_ChainContextPos* ccp = &st->chain;
4955
4956 switch ( ccp->PosFormat )
4957 {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00004958 case 1: Free_ChainContextPos1( &ccp->ccpf.ccpf1 ); break;
4959 case 2: Free_ChainContextPos2( &ccp->ccpf.ccpf2 ); break;
4960 case 3: Free_ChainContextPos3( &ccp->ccpf.ccpf3 ); break;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004961 default: break;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004962 }
4963}
4964
4965
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004966static HB_Error Lookup_ChainContextPos1(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004967 GPOS_Instance* gpi,
4968 HB_ChainContextPosFormat1* ccpf1,
4969 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004970 HB_UShort flags,
4971 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004972 int nesting_level )
4973{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00004974 HB_UShort index, property;
4975 HB_UShort i, j, k, num_cpr;
4976 HB_UShort bgc, igc, lgc;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00004977 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004978 HB_GPOSHeader* gpos = gpi->gpos;
4979
4980 HB_ChainPosRule* cpr;
4981 HB_ChainPosRule curr_cpr;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05004982 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004983
4984
Behdad Esfahbodce48f032009-11-02 14:35:51 -05004985 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004986
Behdad Esfahbodce48f032009-11-02 14:35:51 -05004987 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00004988 return error;
4989
4990 error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
4991 if ( error )
4992 return error;
4993
4994 cpr = ccpf1->ChainPosRuleSet[index].ChainPosRule;
4995 num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
4996
4997 for ( k = 0; k < num_cpr; k++ )
4998 {
4999 curr_cpr = cpr[k];
5000 bgc = curr_cpr.BacktrackGlyphCount;
5001 igc = curr_cpr.InputGlyphCount;
5002 lgc = curr_cpr.LookaheadGlyphCount;
5003
5004 if ( context_length != 0xFFFF && context_length < igc )
5005 goto next_chainposrule;
5006
5007 /* check whether context is too long; it is a first guess only */
5008
5009 if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
5010 goto next_chainposrule;
5011
5012 if ( bgc )
5013 {
5014 /* Since we don't know in advance the number of glyphs to inspect,
5015 we search backwards for matches in the backtrack glyph array */
5016
5017 for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
5018 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005019 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005020 {
5021 if ( error && error != HB_Err_Not_Covered )
5022 return error;
5023
5024 if ( j + 1 == bgc - i )
5025 goto next_chainposrule;
5026 j--;
5027 }
5028
5029 /* In OpenType 1.3, it is undefined whether the offsets of
5030 backtrack glyphs is in logical order or not. Version 1.4
5031 will clarify this:
5032
5033 Logical order - a b c d e f g h i j
5034 i
5035 Input offsets - 0 1
5036 Backtrack offsets - 3 2 1 0
5037 Lookahead offsets - 0 1 2 3 */
5038
5039 if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
5040 goto next_chainposrule;
5041 }
5042 }
5043
5044 /* Start at 1 because [0] is implied */
5045
5046 for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
5047 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005048 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005049 {
5050 if ( error && error != HB_Err_Not_Covered )
5051 return error;
5052
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005053 if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005054 goto next_chainposrule;
5055 j++;
5056 }
5057
5058 if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
5059 goto next_chainposrule;
5060 }
5061
5062 /* we are starting to check for lookahead glyphs right after the
5063 last context glyph */
5064
5065 for ( i = 0; i < lgc; i++, j++ )
5066 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005067 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005068 {
5069 if ( error && error != HB_Err_Not_Covered )
5070 return error;
5071
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005072 if ( j + lgc - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005073 goto next_chainposrule;
5074 j++;
5075 }
5076
5077 if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
5078 goto next_chainposrule;
5079 }
5080
5081 return Do_ContextPos( gpi, igc,
5082 curr_cpr.PosCount,
5083 curr_cpr.PosLookupRecord,
5084 buffer,
5085 nesting_level );
5086
5087 next_chainposrule:
5088 ;
5089 }
5090
5091 return HB_Err_Not_Covered;
5092}
5093
5094
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005095static HB_Error Lookup_ChainContextPos2(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005096 GPOS_Instance* gpi,
5097 HB_ChainContextPosFormat2* ccpf2,
5098 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005099 HB_UShort flags,
5100 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005101 int nesting_level )
5102{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005103 HB_UShort index, property;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005104 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005105 HB_UShort i, j, k;
5106 HB_UShort bgc, igc, lgc;
5107 HB_UShort known_backtrack_classes,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005108 known_input_classes,
5109 known_lookahead_classes;
5110
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005111 HB_UShort* backtrack_classes;
5112 HB_UShort* input_classes;
5113 HB_UShort* lookahead_classes;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005114
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005115 HB_UShort* bc;
5116 HB_UShort* ic;
5117 HB_UShort* lc;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005118 HB_GPOSHeader* gpos = gpi->gpos;
5119
5120 HB_ChainPosClassSet* cpcs;
5121 HB_ChainPosClassRule cpcr;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005122 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005123
5124
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005125 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005126
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005127 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005128 return error;
5129
5130 /* Note: The coverage table in format 2 doesn't give an index into
5131 anything. It just lets us know whether or not we need to
5132 do any lookup at all. */
5133
5134 error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
5135 if ( error )
5136 return error;
5137
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005138 if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005139 return error;
5140 known_backtrack_classes = 0;
5141
Behdad Esfahbodd49caf12009-03-02 15:16:11 +03305142 if (ccpf2->MaxInputLength < 1)
5143 return HB_Err_Not_Covered;
5144
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005145 if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005146 goto End3;
5147 known_input_classes = 1;
5148
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005149 if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, HB_UShort ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005150 goto End2;
5151 known_lookahead_classes = 0;
5152
5153 error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
5154 &input_classes[0], NULL );
5155 if ( error && error != HB_Err_Not_Covered )
5156 goto End1;
5157
5158 cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
5159 if ( !cpcs )
5160 {
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005161 error = ERR(HB_Err_Invalid_SubTable);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005162 goto End1;
5163 }
5164
5165 for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
5166 {
5167 cpcr = cpcs->ChainPosClassRule[k];
5168 bgc = cpcr.BacktrackGlyphCount;
5169 igc = cpcr.InputGlyphCount;
5170 lgc = cpcr.LookaheadGlyphCount;
5171
5172 if ( context_length != 0xFFFF && context_length < igc )
5173 goto next_chainposclassrule;
5174
5175 /* check whether context is too long; it is a first guess only */
5176
5177 if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
5178 goto next_chainposclassrule;
5179
5180 if ( bgc )
5181 {
5182 /* Since we don't know in advance the number of glyphs to inspect,
5183 we search backwards for matches in the backtrack glyph array.
5184 Note that `known_backtrack_classes' starts at index 0. */
5185
5186 bc = cpcr.Backtrack;
5187
5188 for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
5189 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005190 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005191 {
5192 if ( error && error != HB_Err_Not_Covered )
5193 goto End1;
5194
5195 if ( j + 1 == bgc - i )
5196 goto next_chainposclassrule;
5197 j++;
5198 }
5199
5200 if ( i >= known_backtrack_classes )
5201 {
5202 /* Keeps us from having to do this for each rule */
5203
5204 error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
5205 &backtrack_classes[i], NULL );
5206 if ( error && error != HB_Err_Not_Covered )
5207 goto End1;
5208 known_backtrack_classes = i;
5209 }
5210
5211 if ( bc[i] != backtrack_classes[i] )
5212 goto next_chainposclassrule;
5213 }
5214 }
5215
5216 ic = cpcr.Input;
5217
5218 /* Start at 1 because [0] is implied */
5219
5220 for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
5221 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005222 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005223 {
5224 if ( error && error != HB_Err_Not_Covered )
5225 goto End1;
5226
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005227 if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005228 goto next_chainposclassrule;
5229 j++;
5230 }
5231
5232 if ( i >= known_input_classes )
5233 {
5234 error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
5235 &input_classes[i], NULL );
5236 if ( error && error != HB_Err_Not_Covered )
5237 goto End1;
5238 known_input_classes = i;
5239 }
5240
5241 if ( ic[i - 1] != input_classes[i] )
5242 goto next_chainposclassrule;
5243 }
5244
5245 /* we are starting to check for lookahead glyphs right after the
5246 last context glyph */
5247
5248 lc = cpcr.Lookahead;
5249
5250 for ( i = 0; i < lgc; i++, j++ )
5251 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005252 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005253 {
5254 if ( error && error != HB_Err_Not_Covered )
5255 goto End1;
5256
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005257 if ( j + lgc - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005258 goto next_chainposclassrule;
5259 j++;
5260 }
5261
5262 if ( i >= known_lookahead_classes )
5263 {
5264 error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
5265 &lookahead_classes[i], NULL );
5266 if ( error && error != HB_Err_Not_Covered )
5267 goto End1;
5268 known_lookahead_classes = i;
5269 }
5270
5271 if ( lc[i] != lookahead_classes[i] )
5272 goto next_chainposclassrule;
5273 }
5274
5275 error = Do_ContextPos( gpi, igc,
5276 cpcr.PosCount,
5277 cpcr.PosLookupRecord,
5278 buffer,
5279 nesting_level );
5280 goto End1;
5281
5282 next_chainposclassrule:
5283 ;
5284 }
5285
5286 error = HB_Err_Not_Covered;
5287
5288End1:
5289 FREE( lookahead_classes );
5290
5291End2:
5292 FREE( input_classes );
5293
5294End3:
5295 FREE( backtrack_classes );
5296 return error;
5297}
5298
5299
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005300static HB_Error Lookup_ChainContextPos3(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005301 GPOS_Instance* gpi,
5302 HB_ChainContextPosFormat3* ccpf3,
5303 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005304 HB_UShort flags,
5305 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005306 int nesting_level )
5307{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005308 HB_UShort index, i, j, property;
5309 HB_UShort bgc, igc, lgc;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005310 HB_Error error;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005311 HB_GPOSHeader* gpos = gpi->gpos;
5312
5313 HB_Coverage* bc;
5314 HB_Coverage* ic;
5315 HB_Coverage* lc;
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005316 hb_ot_layout_t* layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005317
5318
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005319 layout = gpos->layout;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005320
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005321 if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005322 return error;
5323
5324 bgc = ccpf3->BacktrackGlyphCount;
5325 igc = ccpf3->InputGlyphCount;
5326 lgc = ccpf3->LookaheadGlyphCount;
5327
5328 if ( context_length != 0xFFFF && context_length < igc )
5329 return HB_Err_Not_Covered;
5330
5331 /* check whether context is too long; it is a first guess only */
5332
5333 if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
5334 return HB_Err_Not_Covered;
5335
5336 if ( bgc )
5337 {
5338 /* Since we don't know in advance the number of glyphs to inspect,
5339 we search backwards for matches in the backtrack glyph array */
5340
5341 bc = ccpf3->BacktrackCoverage;
5342
5343 for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
5344 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005345 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005346 {
5347 if ( error && error != HB_Err_Not_Covered )
5348 return error;
5349
5350 if ( j + 1 == bgc - i )
5351 return HB_Err_Not_Covered;
5352 j--;
5353 }
5354
5355 error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
5356 if ( error )
5357 return error;
5358 }
5359 }
5360
5361 ic = ccpf3->InputCoverage;
5362
5363 for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
5364 {
5365 /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005366 while ( j > buffer->in_pos && CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005367 {
5368 if ( error && error != HB_Err_Not_Covered )
5369 return error;
5370
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005371 if ( j + igc - i + lgc == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005372 return HB_Err_Not_Covered;
5373 j++;
5374 }
5375
5376 error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
5377 if ( error )
5378 return error;
5379 }
5380
5381 /* we are starting to check for lookahead glyphs right after the
5382 last context glyph */
5383
5384 lc = ccpf3->LookaheadCoverage;
5385
5386 for ( i = 0; i < lgc; i++, j++ )
5387 {
Behdad Esfahbodce48f032009-11-02 14:35:51 -05005388 while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005389 {
5390 if ( error && error != HB_Err_Not_Covered )
5391 return error;
5392
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005393 if ( j + lgc - i == (HB_Int)buffer->in_length )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005394 return HB_Err_Not_Covered;
5395 j++;
5396 }
5397
5398 error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
5399 if ( error )
5400 return error;
5401 }
5402
5403 return Do_ContextPos( gpi, igc,
5404 ccpf3->PosCount,
5405 ccpf3->PosLookupRecord,
5406 buffer,
5407 nesting_level );
5408}
5409
5410
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005411static HB_Error Lookup_ChainContextPos(
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005412 GPOS_Instance* gpi,
5413 HB_GPOS_SubTable* st,
5414 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005415 HB_UShort flags,
5416 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005417 int nesting_level )
5418{
5419 HB_ChainContextPos* ccp = &st->chain;
5420
5421 switch ( ccp->PosFormat )
5422 {
5423 case 1:
5424 return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
5425 flags, context_length,
5426 nesting_level );
5427
5428 case 2:
5429 return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
5430 flags, context_length,
5431 nesting_level );
5432
5433 case 3:
5434 return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
5435 flags, context_length,
5436 nesting_level );
5437
5438 default:
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005439 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005440 }
5441
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005442 return HB_Err_Ok; /* never reached */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005443}
5444
5445
5446
5447/***********
5448 * GPOS API
5449 ***********/
5450
5451
5452
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005453HB_Error HB_GPOS_Select_Script( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005454 HB_UInt script_tag,
5455 HB_UShort* script_index )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005456{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005457 HB_UShort n;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005458
5459 HB_ScriptList* sl;
5460 HB_ScriptRecord* sr;
5461
5462
5463 if ( !gpos || !script_index )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005464 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005465
5466 sl = &gpos->ScriptList;
5467 sr = sl->ScriptRecord;
5468
5469 for ( n = 0; n < sl->ScriptCount; n++ )
5470 if ( script_tag == sr[n].ScriptTag )
5471 {
5472 *script_index = n;
5473
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005474 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005475 }
5476
5477 return HB_Err_Not_Covered;
5478}
5479
5480
5481
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005482HB_Error HB_GPOS_Select_Language( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005483 HB_UInt language_tag,
5484 HB_UShort script_index,
5485 HB_UShort* language_index,
5486 HB_UShort* req_feature_index )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005487{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005488 HB_UShort n;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005489
5490 HB_ScriptList* sl;
5491 HB_ScriptRecord* sr;
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005492 HB_ScriptTable* s;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005493 HB_LangSysRecord* lsr;
5494
5495
5496 if ( !gpos || !language_index || !req_feature_index )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005497 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005498
5499 sl = &gpos->ScriptList;
5500 sr = sl->ScriptRecord;
5501
5502 if ( script_index >= sl->ScriptCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005503 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005504
5505 s = &sr[script_index].Script;
5506 lsr = s->LangSysRecord;
5507
5508 for ( n = 0; n < s->LangSysCount; n++ )
5509 if ( language_tag == lsr[n].LangSysTag )
5510 {
5511 *language_index = n;
5512 *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
5513
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005514 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005515 }
5516
5517 return HB_Err_Not_Covered;
5518}
5519
5520
5521/* selecting 0xFFFF for language_index asks for the values of the
5522 default language (DefaultLangSys) */
5523
5524
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005525HB_Error HB_GPOS_Select_Feature( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005526 HB_UInt feature_tag,
5527 HB_UShort script_index,
5528 HB_UShort language_index,
5529 HB_UShort* feature_index )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005530{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005531 HB_UShort n;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005532
5533 HB_ScriptList* sl;
5534 HB_ScriptRecord* sr;
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005535 HB_ScriptTable* s;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005536 HB_LangSysRecord* lsr;
5537 HB_LangSys* ls;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005538 HB_UShort* fi;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005539
5540 HB_FeatureList* fl;
5541 HB_FeatureRecord* fr;
5542
5543
5544 if ( !gpos || !feature_index )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005545 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005546
5547 sl = &gpos->ScriptList;
5548 sr = sl->ScriptRecord;
5549
5550 fl = &gpos->FeatureList;
5551 fr = fl->FeatureRecord;
5552
5553 if ( script_index >= sl->ScriptCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005554 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005555
5556 s = &sr[script_index].Script;
5557 lsr = s->LangSysRecord;
5558
5559 if ( language_index == 0xFFFF )
5560 ls = &s->DefaultLangSys;
5561 else
5562 {
5563 if ( language_index >= s->LangSysCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005564 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005565
5566 ls = &lsr[language_index].LangSys;
5567 }
5568
5569 fi = ls->FeatureIndex;
5570
5571 for ( n = 0; n < ls->FeatureCount; n++ )
5572 {
5573 if ( fi[n] >= fl->FeatureCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005574 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005575
5576 if ( feature_tag == fr[fi[n]].FeatureTag )
5577 {
5578 *feature_index = fi[n];
5579
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005580 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005581 }
5582 }
5583
5584 return HB_Err_Not_Covered;
5585}
5586
5587
5588/* The next three functions return a null-terminated list */
5589
5590
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005591HB_Error HB_GPOS_Query_Scripts( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005592 HB_UInt** script_tag_list )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005593{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005594 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005595 HB_UShort n;
5596 HB_UInt* stl;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005597
5598 HB_ScriptList* sl;
5599 HB_ScriptRecord* sr;
5600
5601
5602 if ( !gpos || !script_tag_list )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005603 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005604
5605 sl = &gpos->ScriptList;
5606 sr = sl->ScriptRecord;
5607
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005608 if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, HB_UInt ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005609 return error;
5610
5611 for ( n = 0; n < sl->ScriptCount; n++ )
5612 stl[n] = sr[n].ScriptTag;
5613 stl[n] = 0;
5614
5615 *script_tag_list = stl;
5616
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005617 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005618}
5619
5620
5621
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005622HB_Error HB_GPOS_Query_Languages( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005623 HB_UShort script_index,
5624 HB_UInt** language_tag_list )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005625{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005626 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005627 HB_UShort n;
5628 HB_UInt* ltl;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005629
5630 HB_ScriptList* sl;
5631 HB_ScriptRecord* sr;
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005632 HB_ScriptTable* s;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005633 HB_LangSysRecord* lsr;
5634
5635
5636 if ( !gpos || !language_tag_list )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005637 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005638
5639 sl = &gpos->ScriptList;
5640 sr = sl->ScriptRecord;
5641
5642 if ( script_index >= sl->ScriptCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005643 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005644
5645 s = &sr[script_index].Script;
5646 lsr = s->LangSysRecord;
5647
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005648 if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, HB_UInt ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005649 return error;
5650
5651 for ( n = 0; n < s->LangSysCount; n++ )
5652 ltl[n] = lsr[n].LangSysTag;
5653 ltl[n] = 0;
5654
5655 *language_tag_list = ltl;
5656
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005657 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005658}
5659
5660
5661/* selecting 0xFFFF for language_index asks for the values of the
5662 default language (DefaultLangSys) */
5663
5664
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005665HB_Error HB_GPOS_Query_Features( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005666 HB_UShort script_index,
5667 HB_UShort language_index,
5668 HB_UInt** feature_tag_list )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005669{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005670 HB_UShort n;
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005671 HB_Error error;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005672 HB_UInt* ftl;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005673
5674 HB_ScriptList* sl;
5675 HB_ScriptRecord* sr;
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005676 HB_ScriptTable* s;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005677 HB_LangSysRecord* lsr;
5678 HB_LangSys* ls;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005679 HB_UShort* fi;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005680
5681 HB_FeatureList* fl;
5682 HB_FeatureRecord* fr;
5683
5684
5685 if ( !gpos || !feature_tag_list )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005686 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005687
5688 sl = &gpos->ScriptList;
5689 sr = sl->ScriptRecord;
5690
5691 fl = &gpos->FeatureList;
5692 fr = fl->FeatureRecord;
5693
5694 if ( script_index >= sl->ScriptCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005695 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005696
5697 s = &sr[script_index].Script;
5698 lsr = s->LangSysRecord;
5699
5700 if ( language_index == 0xFFFF )
5701 ls = &s->DefaultLangSys;
5702 else
5703 {
5704 if ( language_index >= s->LangSysCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005705 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005706
5707 ls = &lsr[language_index].LangSys;
5708 }
5709
5710 fi = ls->FeatureIndex;
5711
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005712 if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, HB_UInt ) )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005713 return error;
5714
5715 for ( n = 0; n < ls->FeatureCount; n++ )
5716 {
5717 if ( fi[n] >= fl->FeatureCount )
5718 {
5719 FREE( ftl );
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005720 return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005721 }
5722 ftl[n] = fr[fi[n]].FeatureTag;
5723 }
5724 ftl[n] = 0;
5725
5726 *feature_tag_list = ftl;
5727
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005728 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005729}
5730
5731
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005732/* Do an individual subtable lookup. Returns HB_Err_Ok if positioning
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005733 has been done, or HB_Err_Not_Covered if not. */
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005734static HB_Error GPOS_Do_Glyph_Lookup( GPOS_Instance* gpi,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005735 HB_UShort lookup_index,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005736 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005737 HB_UShort context_length,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005738 int nesting_level )
5739{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005740 HB_Error error = HB_Err_Not_Covered;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005741 HB_UShort i, flags, lookup_count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005742 HB_GPOSHeader* gpos = gpi->gpos;
5743 HB_Lookup* lo;
5744 int lookup_type;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005745
5746
5747 nesting_level++;
5748
5749 if ( nesting_level > HB_MAX_NESTING_LEVEL )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005750 return ERR(HB_Err_Not_Covered); /* ERR() call intended */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005751
5752 lookup_count = gpos->LookupList.LookupCount;
5753 if (lookup_index >= lookup_count)
5754 return error;
5755
5756 lo = &gpos->LookupList.Lookup[lookup_index];
5757 flags = lo->LookupFlag;
5758 lookup_type = lo->LookupType;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005759
5760 for ( i = 0; i < lo->SubTableCount; i++ )
5761 {
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005762 HB_GPOS_SubTable *st = &lo->SubTable[i].st.gpos;
5763
5764 switch (lookup_type) {
5765 case HB_GPOS_LOOKUP_SINGLE:
5766 error = Lookup_SinglePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5767 case HB_GPOS_LOOKUP_PAIR:
5768 error = Lookup_PairPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5769 case HB_GPOS_LOOKUP_CURSIVE:
5770 error = Lookup_CursivePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5771 case HB_GPOS_LOOKUP_MARKBASE:
5772 error = Lookup_MarkBasePos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5773 case HB_GPOS_LOOKUP_MARKLIG:
5774 error = Lookup_MarkLigPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5775 case HB_GPOS_LOOKUP_MARKMARK:
5776 error = Lookup_MarkMarkPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5777 case HB_GPOS_LOOKUP_CONTEXT:
5778 error = Lookup_ContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5779 case HB_GPOS_LOOKUP_CHAIN:
5780 error = Lookup_ChainContextPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;
5781 /*case HB_GPOS_LOOKUP_EXTENSION:
5782 error = Lookup_ExtensionPos ( gpi, st, buffer, flags, context_length, nesting_level ); break;*/
5783 default:
5784 error = HB_Err_Not_Covered;
5785 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005786
5787 /* Check whether we have a successful positioning or an error other
5788 than HB_Err_Not_Covered */
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005789 if ( error != HB_Err_Not_Covered )
5790 return error;
5791 }
5792
5793 return HB_Err_Not_Covered;
5794}
5795
5796
Behdad Esfahbod6b347132007-10-11 08:30:50 +00005797HB_INTERNAL HB_Error
5798_HB_GPOS_Load_SubTable( HB_GPOS_SubTable* st,
Behdad Esfahbod4280ec42007-10-25 00:23:46 +00005799 HB_Stream stream,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005800 HB_UShort lookup_type )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005801{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005802 switch ( lookup_type ) {
5803 case HB_GPOS_LOOKUP_SINGLE: return Load_SinglePos ( st, stream );
5804 case HB_GPOS_LOOKUP_PAIR: return Load_PairPos ( st, stream );
5805 case HB_GPOS_LOOKUP_CURSIVE: return Load_CursivePos ( st, stream );
5806 case HB_GPOS_LOOKUP_MARKBASE: return Load_MarkBasePos ( st, stream );
5807 case HB_GPOS_LOOKUP_MARKLIG: return Load_MarkLigPos ( st, stream );
5808 case HB_GPOS_LOOKUP_MARKMARK: return Load_MarkMarkPos ( st, stream );
5809 case HB_GPOS_LOOKUP_CONTEXT: return Load_ContextPos ( st, stream );
5810 case HB_GPOS_LOOKUP_CHAIN: return Load_ChainContextPos ( st, stream );
5811 /*case HB_GPOS_LOOKUP_EXTENSION: return Load_ExtensionPos ( st, stream );*/
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005812 default: return ERR(HB_Err_Invalid_SubTable_Format);
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005813 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005814}
5815
5816
Behdad Esfahbod6b347132007-10-11 08:30:50 +00005817HB_INTERNAL void
5818_HB_GPOS_Free_SubTable( HB_GPOS_SubTable* st,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005819 HB_UShort lookup_type )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005820{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005821 switch ( lookup_type ) {
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00005822 case HB_GPOS_LOOKUP_SINGLE: Free_SinglePos ( st ); return;
5823 case HB_GPOS_LOOKUP_PAIR: Free_PairPos ( st ); return;
5824 case HB_GPOS_LOOKUP_CURSIVE: Free_CursivePos ( st ); return;
5825 case HB_GPOS_LOOKUP_MARKBASE: Free_MarkBasePos ( st ); return;
5826 case HB_GPOS_LOOKUP_MARKLIG: Free_MarkLigPos ( st ); return;
5827 case HB_GPOS_LOOKUP_MARKMARK: Free_MarkMarkPos ( st ); return;
5828 case HB_GPOS_LOOKUP_CONTEXT: Free_ContextPos ( st ); return;
5829 case HB_GPOS_LOOKUP_CHAIN: Free_ChainContextPos ( st ); return;
5830 /*case HB_GPOS_LOOKUP_EXTENSION: Free_ExtensionPos ( st ); return;*/
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005831 default: return;
5832 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005833}
5834
5835
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005836/* apply one lookup to the input string object */
5837
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005838static HB_Error GPOS_Do_String_Lookup( GPOS_Instance* gpi,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005839 HB_UShort lookup_index,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005840 HB_Buffer buffer )
5841{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005842 HB_Error error, retError = HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005843 HB_GPOSHeader* gpos = gpi->gpos;
5844
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005845 HB_UInt* properties = gpos->LookupList.Properties;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005846
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005847 const int nesting_level = 0;
5848 /* 0xFFFF indicates that we don't have a context length yet */
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005849 const HB_UShort context_length = 0xFFFF;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005850
5851
5852 gpi->last = 0xFFFF; /* no last valid glyph for cursive pos. */
5853
5854 buffer->in_pos = 0;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005855 while ( buffer->in_pos < buffer->in_length )
5856 {
5857 if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
5858 {
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005859 /* Note that the connection between mark and base glyphs hold
5860 exactly one (string) lookup. For example, it would be possible
5861 that in the first lookup, mark glyph X is attached to base
5862 glyph A, and in the next lookup it is attached to base glyph B.
5863 It is up to the font designer to provide meaningful lookups and
5864 lookup order. */
5865
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005866 error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer, context_length, nesting_level );
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005867 if ( error && error != HB_Err_Not_Covered )
5868 return error;
5869 }
5870 else
5871 {
5872 /* Contrary to properties defined in GDEF, user-defined properties
5873 will always stop a possible cursive positioning. */
5874 gpi->last = 0xFFFF;
5875
5876 error = HB_Err_Not_Covered;
5877 }
5878
5879 if ( error == HB_Err_Not_Covered )
5880 (buffer->in_pos)++;
5881 else
5882 retError = error;
5883 }
5884
5885 return retError;
5886}
5887
5888
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005889static HB_Error Position_CursiveChain ( HB_Buffer buffer )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005890{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005891 HB_UInt i, j;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005892 HB_Position positions = buffer->positions;
5893
5894 /* First handle all left-to-right connections */
Behdad Esfahboda26c6ae2008-09-29 22:28:47 +00005895 for (j = 0; j < buffer->in_length; j++)
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005896 {
5897 if (positions[j].cursive_chain > 0)
5898 positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
5899 }
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00005900
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005901 /* Then handle all right-to-left connections */
5902 for (i = buffer->in_length; i > 0; i--)
5903 {
5904 j = i - 1;
5905
5906 if (positions[j].cursive_chain < 0)
5907 positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
5908 }
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00005909
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005910 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005911}
5912
5913
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005914HB_Error HB_GPOS_Add_Feature( HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005915 HB_UShort feature_index,
5916 HB_UInt property )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005917{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005918 HB_UShort i;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005919
5920 HB_Feature feature;
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005921 HB_UInt* properties;
5922 HB_UShort* index;
5923 HB_UShort lookup_count;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005924
5925 /* Each feature can only be added once */
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00005926
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005927 if ( !gpos ||
5928 feature_index >= gpos->FeatureList.FeatureCount ||
5929 gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005930 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005931
5932 gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
5933
5934 properties = gpos->LookupList.Properties;
5935
5936 feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
5937 index = feature.LookupListIndex;
5938 lookup_count = gpos->LookupList.LookupCount;
5939
5940 for ( i = 0; i < feature.LookupListCount; i++ )
5941 {
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005942 HB_UShort lookup_index = index[i];
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005943 if (lookup_index < lookup_count)
5944 properties[lookup_index] |= property;
5945 }
5946
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005947 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005948}
5949
5950
5951
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005952HB_Error HB_GPOS_Clear_Features( HB_GPOSHeader* gpos )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005953{
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005954 HB_UShort i;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005955
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00005956 HB_UInt* properties;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005957
5958
5959 if ( !gpos )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005960 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005961
5962 gpos->FeatureList.ApplyCount = 0;
5963
5964 properties = gpos->LookupList.Properties;
5965
5966 for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
5967 properties[i] = 0;
5968
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005969 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005970}
5971
5972
5973
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005974HB_Error HB_GPOS_Register_Glyph_Function( HB_GPOSHeader* gpos,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005975 HB_GlyphFunction gfunc )
5976{
5977 if ( !gpos )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005978 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005979
5980 gpos->gfunc = gfunc;
5981
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005982 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005983}
5984
5985
5986
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005987HB_Error HB_GPOS_Register_MM_Function( HB_GPOSHeader* gpos,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005988 HB_MMFunction mmfunc,
5989 void* data )
5990{
5991 if ( !gpos )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00005992 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005993
5994 gpos->mmfunc = mmfunc;
5995 gpos->data = data;
5996
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00005997 return HB_Err_Ok;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00005998}
5999
6000/* If `dvi' is TRUE, glyph contour points for anchor points and device
6001 tables are ignored -- you will get device independent values. */
6002
6003
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00006004HB_Error HB_GPOS_Apply_String( HB_Font font,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006005 HB_GPOSHeader* gpos,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00006006 HB_UShort load_flags,
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006007 HB_Buffer buffer,
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00006008 HB_Bool dvi,
6009 HB_Bool r2l )
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006010{
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00006011 HB_Error error, retError = HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006012 GPOS_Instance gpi;
Behdad Esfahbod06003902007-10-11 07:05:09 +00006013 int i, j, lookup_count, num_features;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006014
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00006015 if ( !font || !gpos || !buffer )
Behdad Esfahbod282c60a2007-10-25 23:22:17 +00006016 return ERR(HB_Err_Invalid_Argument);
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00006017
6018 if ( buffer->in_length == 0 )
6019 return HB_Err_Not_Covered;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006020
Behdad Esfahbod47d2c332007-11-07 09:59:18 +00006021 gpi.font = font;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006022 gpi.gpos = gpos;
6023 gpi.load_flags = load_flags;
6024 gpi.r2l = r2l;
6025 gpi.dvi = dvi;
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00006026
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006027 lookup_count = gpos->LookupList.LookupCount;
Behdad Esfahbod06003902007-10-11 07:05:09 +00006028 num_features = gpos->FeatureList.ApplyCount;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006029
Behdad Esfahbod06003902007-10-11 07:05:09 +00006030 if ( num_features )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00006031 {
Behdad Esfahbod6b347132007-10-11 08:30:50 +00006032 error = _hb_buffer_clear_positions( buffer );
Behdad Esfahbod06003902007-10-11 07:05:09 +00006033 if ( error )
6034 return error;
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00006035 }
6036
Behdad Esfahbod06003902007-10-11 07:05:09 +00006037 for ( i = 0; i < num_features; i++ )
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00006038 {
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00006039 HB_UShort feature_index = gpos->FeatureList.ApplyOrder[i];
Behdad Esfahboda8abb8b2007-10-11 00:07:58 +00006040 HB_Feature feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006041
6042 for ( j = 0; j < feature.LookupListCount; j++ )
6043 {
Behdad Esfahbod5716ae22007-10-24 22:44:47 +00006044 HB_UShort lookup_index = feature.LookupListIndex[j];
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006045
6046 /* Skip nonexistant lookups */
6047 if (lookup_index >= lookup_count)
6048 continue;
6049
6050 error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
6051 if ( error )
6052 {
6053 if ( error != HB_Err_Not_Covered )
6054 return error;
6055 }
6056 else
6057 retError = error;
6058 }
6059 }
Behdad Esfahbodb31d6de2006-04-06 18:23:49 +00006060
Behdad Esfahbod06003902007-10-11 07:05:09 +00006061 if ( num_features )
Behdad Esfahbodfc3d6f52007-10-11 06:52:07 +00006062 {
6063 error = Position_CursiveChain ( buffer );
6064 if ( error )
6065 return error;
6066 }
Behdad Esfahbod9f8da382006-03-31 12:28:09 +00006067
6068 return retError;
6069}
6070
6071/* END */