~ubuntu-branches/ubuntu/karmic/pango1.0/karmic-security

« back to all changes in this revision

Viewing changes to pango/opentype/harfbuzz-gpos.c

Tags: upstream-1.15.4
ImportĀ upstreamĀ versionĀ 1.15.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************
 
2
 *
 
3
 *  Copyright 1996-2000 by
 
4
 *  David Turner, Robert Wilhelm, and Werner Lemberg.
 
5
 *
 
6
 *  Copyright 2006  Behdad Esfahbod
 
7
 *
 
8
 *  This is part of HarfBuzz, an OpenType Layout engine library.
 
9
 *
 
10
 *  See the file name COPYING for licensing information.
 
11
 *
 
12
 ******************************************************************/
 
13
#include "harfbuzz-impl.h"
 
14
#include "harfbuzz-gpos-private.h"
 
15
#include "harfbuzz-open-private.h"
 
16
#include "harfbuzz-gdef-private.h"
 
17
 
 
18
struct  GPOS_Instance_
 
19
{
 
20
  HB_GPOSHeader*  gpos;
 
21
  FT_Face          face;
 
22
  FT_Bool          dvi;
 
23
  FT_UShort        load_flags;  /* how the glyph should be loaded */
 
24
  FT_Bool          r2l;
 
25
 
 
26
  FT_UShort        last;        /* the last valid glyph -- used
 
27
                                   with cursive positioning     */
 
28
  FT_Pos           anchor_x;    /* the coordinates of the anchor point */
 
29
  FT_Pos           anchor_y;    /* of the last valid glyph             */
 
30
};
 
31
 
 
32
typedef struct GPOS_Instance_  GPOS_Instance;
 
33
 
 
34
 
 
35
static FT_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
 
36
                                       FT_UShort         lookup_index,
 
37
                                       HB_Buffer        buffer,
 
38
                                       FT_UShort         context_length,
 
39
                                       int               nesting_level );
 
40
 
 
41
 
 
42
 
 
43
/* the client application must replace this with something more
 
44
   meaningful if multiple master fonts are to be supported.     */
 
45
 
 
46
static FT_Error  default_mmfunc( FT_Face      face,
 
47
                                 FT_UShort    metric_id,
 
48
                                 FT_Pos*      metric_value,
 
49
                                 void*        data )
 
50
{
 
51
  FT_UNUSED(face);
 
52
  FT_UNUSED(metric_id);
 
53
  FT_UNUSED(metric_value);
 
54
  FT_UNUSED(data);
 
55
  return HB_Err_No_MM_Interpreter;
 
56
}
 
57
 
 
58
 
 
59
 
 
60
FT_Error  HB_Load_GPOS_Table( FT_Face          face,
 
61
                              HB_GPOSHeader** retptr,
 
62
                              HB_GDEFHeader*  gdef )
 
63
{
 
64
  FT_ULong         cur_offset, new_offset, base_offset;
 
65
 
 
66
  FT_UShort        i, num_lookups;
 
67
  HB_GPOSHeader*  gpos;
 
68
  HB_Lookup*      lo;
 
69
 
 
70
  FT_Stream  stream = face->stream;
 
71
  FT_Error   error;
 
72
  FT_Memory  memory = face->memory;
 
73
 
 
74
 
 
75
  if ( !retptr )
 
76
    return FT_Err_Invalid_Argument;
 
77
 
 
78
  if ( !stream )
 
79
    return FT_Err_Invalid_Face_Handle;
 
80
 
 
81
  if (( error = _hb_ftglue_face_goto_table( face, TTAG_GPOS, stream ) ))
 
82
    return error;
 
83
 
 
84
  base_offset = FILE_Pos();
 
85
 
 
86
  if ( ALLOC ( gpos, sizeof( *gpos ) ) )
 
87
    return error;
 
88
 
 
89
  gpos->memory = memory;
 
90
  gpos->gfunc = FT_Load_Glyph;
 
91
  gpos->mmfunc = default_mmfunc;
 
92
 
 
93
  /* skip version */
 
94
 
 
95
  if ( FILE_Seek( base_offset + 4L ) ||
 
96
       ACCESS_Frame( 2L ) )
 
97
    goto Fail4;
 
98
 
 
99
  new_offset = GET_UShort() + base_offset;
 
100
 
 
101
  FORGET_Frame();
 
102
 
 
103
  cur_offset = FILE_Pos();
 
104
  if ( FILE_Seek( new_offset ) ||
 
105
       ( error = _HB_OPEN_Load_ScriptList( &gpos->ScriptList,
 
106
                                  stream ) ) != FT_Err_Ok )
 
107
    goto Fail4;
 
108
  (void)FILE_Seek( cur_offset );
 
109
 
 
110
  if ( ACCESS_Frame( 2L ) )
 
111
    goto Fail3;
 
112
 
 
113
  new_offset = GET_UShort() + base_offset;
 
114
 
 
115
  FORGET_Frame();
 
116
 
 
117
  cur_offset = FILE_Pos();
 
118
  if ( FILE_Seek( new_offset ) ||
 
119
       ( error = _HB_OPEN_Load_FeatureList( &gpos->FeatureList,
 
120
                                   stream ) ) != FT_Err_Ok )
 
121
    goto Fail3;
 
122
  (void)FILE_Seek( cur_offset );
 
123
 
 
124
  if ( ACCESS_Frame( 2L ) )
 
125
    goto Fail2;
 
126
 
 
127
  new_offset = GET_UShort() + base_offset;
 
128
 
 
129
  FORGET_Frame();
 
130
 
 
131
  cur_offset = FILE_Pos();
 
132
  if ( FILE_Seek( new_offset ) ||
 
133
       ( error = _HB_OPEN_Load_LookupList( &gpos->LookupList,
 
134
                                  stream, HB_Type_GPOS ) ) != FT_Err_Ok )
 
135
    goto Fail2;
 
136
 
 
137
  gpos->gdef = gdef;      /* can be NULL */
 
138
 
 
139
  /* We now check the LookupFlags for values larger than 0xFF to find
 
140
     out whether we need to load the `MarkAttachClassDef' field of the
 
141
     GDEF table -- this hack is necessary for OpenType 1.2 tables since
 
142
     the version field of the GDEF table hasn't been incremented.
 
143
 
 
144
     For constructed GDEF tables, we only load it if
 
145
     `MarkAttachClassDef_offset' is not zero (nevertheless, a build of
 
146
     a constructed mark attach table is not supported currently).       */
 
147
 
 
148
  if ( gdef &&
 
149
       gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded )
 
150
  {
 
151
    lo          = gpos->LookupList.Lookup;
 
152
    num_lookups = gpos->LookupList.LookupCount;
 
153
 
 
154
    for ( i = 0; i < num_lookups; i++ )
 
155
    {
 
156
      if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
 
157
      {
 
158
        if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) ||
 
159
             ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef,
 
160
                                             256, stream ) ) != FT_Err_Ok )
 
161
          goto Fail1;
 
162
 
 
163
        break;
 
164
      }
 
165
    }
 
166
  }
 
167
 
 
168
  *retptr = gpos;
 
169
 
 
170
  return FT_Err_Ok;
 
171
 
 
172
Fail1:
 
173
  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
 
174
 
 
175
Fail2:
 
176
  _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
 
177
 
 
178
Fail3:
 
179
  _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
 
180
 
 
181
Fail4:
 
182
  FREE( gpos );
 
183
 
 
184
  return error;
 
185
}
 
186
 
 
187
 
 
188
FT_Error  HB_Done_GPOS_Table( HB_GPOSHeader* gpos )
 
189
{
 
190
  FT_Memory memory = gpos->memory;
 
191
 
 
192
  _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS, memory );
 
193
  _HB_OPEN_Free_FeatureList( &gpos->FeatureList, memory );
 
194
  _HB_OPEN_Free_ScriptList( &gpos->ScriptList, memory );
 
195
 
 
196
  return FT_Err_Ok;
 
197
}
 
198
 
 
199
 
 
200
/*****************************
 
201
 * SubTable related functions
 
202
 *****************************/
 
203
 
 
204
/* shared tables */
 
205
 
 
206
/* ValueRecord */
 
207
 
 
208
/* There is a subtle difference in the specs between a `table' and a
 
209
   `record' -- offsets for device tables in ValueRecords are taken from
 
210
   the parent table and not the parent record.                          */
 
211
 
 
212
static FT_Error  Load_ValueRecord( HB_ValueRecord*  vr,
 
213
                                   FT_UShort         format,
 
214
                                   FT_ULong          base_offset,
 
215
                                   FT_Stream         stream )
 
216
{
 
217
  FT_Error  error;
 
218
  FT_Memory memory = stream->memory;
 
219
 
 
220
  FT_ULong cur_offset, new_offset;
 
221
 
 
222
 
 
223
  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
 
224
  {
 
225
    if ( ACCESS_Frame( 2L ) )
 
226
      return error;
 
227
 
 
228
    vr->XPlacement = GET_Short();
 
229
 
 
230
    FORGET_Frame();
 
231
  }
 
232
  else
 
233
    vr->XPlacement = 0;
 
234
 
 
235
  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
 
236
  {
 
237
    if ( ACCESS_Frame( 2L ) )
 
238
      return error;
 
239
 
 
240
    vr->YPlacement = GET_Short();
 
241
 
 
242
    FORGET_Frame();
 
243
  }
 
244
  else
 
245
    vr->YPlacement = 0;
 
246
 
 
247
  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
 
248
  {
 
249
    if ( ACCESS_Frame( 2L ) )
 
250
      return error;
 
251
 
 
252
    vr->XAdvance = GET_Short();
 
253
 
 
254
    FORGET_Frame();
 
255
  }
 
256
  else
 
257
    vr->XAdvance = 0;
 
258
 
 
259
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
 
260
  {
 
261
    if ( ACCESS_Frame( 2L ) )
 
262
      return error;
 
263
 
 
264
    vr->YAdvance = GET_Short();
 
265
 
 
266
    FORGET_Frame();
 
267
  }
 
268
  else
 
269
    vr->YAdvance = 0;
 
270
 
 
271
  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
 
272
  {
 
273
    if ( ACCESS_Frame( 2L ) )
 
274
      return error;
 
275
 
 
276
    new_offset = GET_UShort();
 
277
 
 
278
    FORGET_Frame();
 
279
 
 
280
    if ( new_offset )
 
281
    {
 
282
      new_offset += base_offset;
 
283
 
 
284
      cur_offset = FILE_Pos();
 
285
      if ( FILE_Seek( new_offset ) ||
 
286
           ( error = _HB_OPEN_Load_Device( &vr->XPlacementDevice,
 
287
                                  stream ) ) != FT_Err_Ok )
 
288
        return error;
 
289
      (void)FILE_Seek( cur_offset );
 
290
    }
 
291
    else
 
292
      goto empty1;
 
293
  }
 
294
  else
 
295
  {
 
296
  empty1:
 
297
    vr->XPlacementDevice.StartSize  = 0;
 
298
    vr->XPlacementDevice.EndSize    = 0;
 
299
    vr->XPlacementDevice.DeltaValue = NULL;
 
300
  }
 
301
 
 
302
  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
 
303
  {
 
304
    if ( ACCESS_Frame( 2L ) )
 
305
      goto Fail3;
 
306
 
 
307
    new_offset = GET_UShort();
 
308
 
 
309
    FORGET_Frame();
 
310
 
 
311
    if ( new_offset )
 
312
    {
 
313
      new_offset += base_offset;
 
314
 
 
315
      cur_offset = FILE_Pos();
 
316
      if ( FILE_Seek( new_offset ) ||
 
317
           ( error = _HB_OPEN_Load_Device( &vr->YPlacementDevice,
 
318
                                  stream ) ) != FT_Err_Ok )
 
319
        goto Fail3;
 
320
      (void)FILE_Seek( cur_offset );
 
321
    }
 
322
    else
 
323
      goto empty2;
 
324
  }
 
325
  else
 
326
  {
 
327
  empty2:
 
328
    vr->YPlacementDevice.StartSize  = 0;
 
329
    vr->YPlacementDevice.EndSize    = 0;
 
330
    vr->YPlacementDevice.DeltaValue = NULL;
 
331
  }
 
332
 
 
333
  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
 
334
  {
 
335
    if ( ACCESS_Frame( 2L ) )
 
336
      goto Fail2;
 
337
 
 
338
    new_offset = GET_UShort();
 
339
 
 
340
    FORGET_Frame();
 
341
 
 
342
    if ( new_offset )
 
343
    {
 
344
      new_offset += base_offset;
 
345
 
 
346
      cur_offset = FILE_Pos();
 
347
      if ( FILE_Seek( new_offset ) ||
 
348
           ( error = _HB_OPEN_Load_Device( &vr->XAdvanceDevice,
 
349
                                  stream ) ) != FT_Err_Ok )
 
350
        goto Fail2;
 
351
      (void)FILE_Seek( cur_offset );
 
352
    }
 
353
    else
 
354
      goto empty3;
 
355
  }
 
356
  else
 
357
  {
 
358
  empty3:
 
359
    vr->XAdvanceDevice.StartSize  = 0;
 
360
    vr->XAdvanceDevice.EndSize    = 0;
 
361
    vr->XAdvanceDevice.DeltaValue = NULL;
 
362
  }
 
363
 
 
364
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
 
365
  {
 
366
    if ( ACCESS_Frame( 2L ) )
 
367
      goto Fail1;
 
368
 
 
369
    new_offset = GET_UShort();
 
370
 
 
371
    FORGET_Frame();
 
372
 
 
373
    if ( new_offset )
 
374
    {
 
375
      new_offset += base_offset;
 
376
 
 
377
      cur_offset = FILE_Pos();
 
378
      if ( FILE_Seek( new_offset ) ||
 
379
           ( error = _HB_OPEN_Load_Device( &vr->YAdvanceDevice,
 
380
                                  stream ) ) != FT_Err_Ok )
 
381
        goto Fail1;
 
382
      (void)FILE_Seek( cur_offset );
 
383
    }
 
384
    else
 
385
      goto empty4;
 
386
  }
 
387
  else
 
388
  {
 
389
  empty4:
 
390
    vr->YAdvanceDevice.StartSize  = 0;
 
391
    vr->YAdvanceDevice.EndSize    = 0;
 
392
    vr->YAdvanceDevice.DeltaValue = NULL;
 
393
  }
 
394
 
 
395
  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
 
396
  {
 
397
    if ( ACCESS_Frame( 2L ) )
 
398
      goto Fail1;
 
399
 
 
400
    vr->XIdPlacement = GET_UShort();
 
401
 
 
402
    FORGET_Frame();
 
403
  }
 
404
  else
 
405
    vr->XIdPlacement = 0;
 
406
 
 
407
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
 
408
  {
 
409
    if ( ACCESS_Frame( 2L ) )
 
410
      goto Fail1;
 
411
 
 
412
    vr->YIdPlacement = GET_UShort();
 
413
 
 
414
    FORGET_Frame();
 
415
  }
 
416
  else
 
417
    vr->YIdPlacement = 0;
 
418
 
 
419
  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
 
420
  {
 
421
    if ( ACCESS_Frame( 2L ) )
 
422
      goto Fail1;
 
423
 
 
424
    vr->XIdAdvance = GET_UShort();
 
425
 
 
426
    FORGET_Frame();
 
427
  }
 
428
  else
 
429
    vr->XIdAdvance = 0;
 
430
 
 
431
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
 
432
  {
 
433
    if ( ACCESS_Frame( 2L ) )
 
434
      goto Fail1;
 
435
 
 
436
    vr->YIdAdvance = GET_UShort();
 
437
 
 
438
    FORGET_Frame();
 
439
  }
 
440
  else
 
441
    vr->YIdAdvance = 0;
 
442
 
 
443
  return FT_Err_Ok;
 
444
 
 
445
Fail1:
 
446
  _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
 
447
 
 
448
Fail2:
 
449
  _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
 
450
 
 
451
Fail3:
 
452
  _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
 
453
  return error;
 
454
}
 
455
 
 
456
 
 
457
static void  Free_ValueRecord( HB_ValueRecord*  vr,
 
458
                               FT_UShort         format,
 
459
                               FT_Memory         memory )
 
460
{
 
461
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
 
462
    _HB_OPEN_Free_Device( &vr->YAdvanceDevice, memory );
 
463
  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
 
464
    _HB_OPEN_Free_Device( &vr->XAdvanceDevice, memory );
 
465
  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
 
466
    _HB_OPEN_Free_Device( &vr->YPlacementDevice, memory );
 
467
  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
 
468
    _HB_OPEN_Free_Device( &vr->XPlacementDevice, memory );
 
469
}
 
470
 
 
471
 
 
472
static FT_Error  Get_ValueRecord( GPOS_Instance*    gpi,
 
473
                                  HB_ValueRecord*  vr,
 
474
                                  FT_UShort         format,
 
475
                                  HB_Position      gd )
 
476
{
 
477
  FT_Pos           value;
 
478
  FT_Short         pixel_value;
 
479
  FT_Error         error = FT_Err_Ok;
 
480
  HB_GPOSHeader*  gpos = gpi->gpos;
 
481
 
 
482
  FT_UShort  x_ppem, y_ppem;
 
483
  FT_Fixed   x_scale, y_scale;
 
484
 
 
485
 
 
486
  if ( !format )
 
487
    return FT_Err_Ok;
 
488
 
 
489
  x_ppem  = gpi->face->size->metrics.x_ppem;
 
490
  y_ppem  = gpi->face->size->metrics.y_ppem;
 
491
  x_scale = gpi->face->size->metrics.x_scale;
 
492
  y_scale = gpi->face->size->metrics.y_scale;
 
493
 
 
494
  /* design units -> fractional pixel */
 
495
 
 
496
  if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT )
 
497
    gd->x_pos += x_scale * vr->XPlacement / 0x10000;
 
498
  if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT )
 
499
    gd->y_pos += y_scale * vr->YPlacement / 0x10000;
 
500
  if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE )
 
501
    gd->x_advance += x_scale * vr->XAdvance / 0x10000;
 
502
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE )
 
503
    gd->y_advance += y_scale * vr->YAdvance / 0x10000;
 
504
 
 
505
  if ( !gpi->dvi )
 
506
  {
 
507
    /* pixel -> fractional pixel */
 
508
 
 
509
    if ( format & HB_GPOS_FORMAT_HAVE_X_PLACEMENT_DEVICE )
 
510
    {
 
511
      _HB_OPEN_Get_Device( &vr->XPlacementDevice, x_ppem, &pixel_value );
 
512
      gd->x_pos += pixel_value << 6;
 
513
    }
 
514
    if ( format & HB_GPOS_FORMAT_HAVE_Y_PLACEMENT_DEVICE )
 
515
    {
 
516
      _HB_OPEN_Get_Device( &vr->YPlacementDevice, y_ppem, &pixel_value );
 
517
      gd->y_pos += pixel_value << 6;
 
518
    }
 
519
    if ( format & HB_GPOS_FORMAT_HAVE_X_ADVANCE_DEVICE )
 
520
    {
 
521
      _HB_OPEN_Get_Device( &vr->XAdvanceDevice, x_ppem, &pixel_value );
 
522
      gd->x_advance += pixel_value << 6;
 
523
    }
 
524
    if ( format & HB_GPOS_FORMAT_HAVE_Y_ADVANCE_DEVICE )
 
525
    {
 
526
      _HB_OPEN_Get_Device( &vr->YAdvanceDevice, y_ppem, &pixel_value );
 
527
      gd->y_advance += pixel_value << 6;
 
528
    }
 
529
  }
 
530
 
 
531
  /* values returned from mmfunc() are already in fractional pixels */
 
532
 
 
533
  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_PLACEMENT )
 
534
  {
 
535
    error = (gpos->mmfunc)( gpi->face, vr->XIdPlacement,
 
536
                            &value, gpos->data );
 
537
    if ( error )
 
538
      return error;
 
539
    gd->x_pos += value;
 
540
  }
 
541
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_PLACEMENT )
 
542
  {
 
543
    error = (gpos->mmfunc)( gpi->face, vr->YIdPlacement,
 
544
                            &value, gpos->data );
 
545
    if ( error )
 
546
      return error;
 
547
    gd->y_pos += value;
 
548
  }
 
549
  if ( format & HB_GPOS_FORMAT_HAVE_X_ID_ADVANCE )
 
550
  {
 
551
    error = (gpos->mmfunc)( gpi->face, vr->XIdAdvance,
 
552
                            &value, gpos->data );
 
553
    if ( error )
 
554
      return error;
 
555
    gd->x_advance += value;
 
556
  }
 
557
  if ( format & HB_GPOS_FORMAT_HAVE_Y_ID_ADVANCE )
 
558
  {
 
559
    error = (gpos->mmfunc)( gpi->face, vr->YIdAdvance,
 
560
                            &value, gpos->data );
 
561
    if ( error )
 
562
      return error;
 
563
    gd->y_advance += value;
 
564
  }
 
565
 
 
566
  return error;
 
567
}
 
568
 
 
569
 
 
570
/* AnchorFormat1 */
 
571
/* AnchorFormat2 */
 
572
/* AnchorFormat3 */
 
573
/* AnchorFormat4 */
 
574
 
 
575
static FT_Error  Load_Anchor( HB_Anchor*  an,
 
576
                              FT_Stream    stream )
 
577
{
 
578
  FT_Error  error;
 
579
  FT_Memory memory = stream->memory;
 
580
 
 
581
  FT_ULong cur_offset, new_offset, base_offset;
 
582
 
 
583
 
 
584
  base_offset = FILE_Pos();
 
585
 
 
586
  if ( ACCESS_Frame( 2L ) )
 
587
    return error;
 
588
 
 
589
  an->PosFormat = GET_UShort();
 
590
 
 
591
  FORGET_Frame();
 
592
 
 
593
  switch ( an->PosFormat )
 
594
  {
 
595
  case 1:
 
596
    if ( ACCESS_Frame( 4L ) )
 
597
      return error;
 
598
 
 
599
    an->af.af1.XCoordinate = GET_Short();
 
600
    an->af.af1.YCoordinate = GET_Short();
 
601
 
 
602
    FORGET_Frame();
 
603
    break;
 
604
 
 
605
  case 2:
 
606
    if ( ACCESS_Frame( 6L ) )
 
607
      return error;
 
608
 
 
609
    an->af.af2.XCoordinate = GET_Short();
 
610
    an->af.af2.YCoordinate = GET_Short();
 
611
    an->af.af2.AnchorPoint = GET_UShort();
 
612
 
 
613
    FORGET_Frame();
 
614
    break;
 
615
 
 
616
  case 3:
 
617
    if ( ACCESS_Frame( 6L ) )
 
618
      return error;
 
619
 
 
620
    an->af.af3.XCoordinate = GET_Short();
 
621
    an->af.af3.YCoordinate = GET_Short();
 
622
 
 
623
    new_offset = GET_UShort();
 
624
 
 
625
    FORGET_Frame();
 
626
 
 
627
    if ( new_offset )
 
628
    {
 
629
      new_offset += base_offset;
 
630
 
 
631
      cur_offset = FILE_Pos();
 
632
      if ( FILE_Seek( new_offset ) ||
 
633
           ( error = _HB_OPEN_Load_Device( &an->af.af3.XDeviceTable,
 
634
                                  stream ) ) != FT_Err_Ok )
 
635
        return error;
 
636
      (void)FILE_Seek( cur_offset );
 
637
    }
 
638
    else
 
639
    {
 
640
      an->af.af3.XDeviceTable.StartSize  = 0;
 
641
      an->af.af3.XDeviceTable.EndSize    = 0;
 
642
      an->af.af3.XDeviceTable.DeltaValue = NULL;
 
643
    }
 
644
 
 
645
    if ( ACCESS_Frame( 2L ) )
 
646
      goto Fail;
 
647
 
 
648
    new_offset = GET_UShort();
 
649
 
 
650
    FORGET_Frame();
 
651
 
 
652
    if ( new_offset )
 
653
    {
 
654
      new_offset += base_offset;
 
655
 
 
656
      cur_offset = FILE_Pos();
 
657
      if ( FILE_Seek( new_offset ) ||
 
658
           ( error = _HB_OPEN_Load_Device( &an->af.af3.YDeviceTable,
 
659
                                  stream ) ) != FT_Err_Ok )
 
660
        goto Fail;
 
661
      (void)FILE_Seek( cur_offset );
 
662
    }
 
663
    else
 
664
    {
 
665
      an->af.af3.YDeviceTable.StartSize  = 0;
 
666
      an->af.af3.YDeviceTable.EndSize    = 0;
 
667
      an->af.af3.YDeviceTable.DeltaValue = NULL;
 
668
    }
 
669
    break;
 
670
 
 
671
  case 4:
 
672
    if ( ACCESS_Frame( 4L ) )
 
673
      return error;
 
674
 
 
675
    an->af.af4.XIdAnchor = GET_UShort();
 
676
    an->af.af4.YIdAnchor = GET_UShort();
 
677
 
 
678
    FORGET_Frame();
 
679
    break;
 
680
 
 
681
  default:
 
682
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
683
  }
 
684
 
 
685
  return FT_Err_Ok;
 
686
 
 
687
Fail:
 
688
  _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
 
689
  return error;
 
690
}
 
691
 
 
692
 
 
693
static void  Free_Anchor( HB_Anchor*  an,
 
694
                          FT_Memory    memory)
 
695
{
 
696
  if ( an->PosFormat == 3 )
 
697
  {
 
698
    _HB_OPEN_Free_Device( &an->af.af3.YDeviceTable, memory );
 
699
    _HB_OPEN_Free_Device( &an->af.af3.XDeviceTable, memory );
 
700
  }
 
701
}
 
702
 
 
703
 
 
704
static FT_Error  Get_Anchor( GPOS_Instance*   gpi,
 
705
                             HB_Anchor*      an,
 
706
                             FT_UShort        glyph_index,
 
707
                             FT_Pos*          x_value,
 
708
                             FT_Pos*          y_value )
 
709
{
 
710
  FT_Error  error = FT_Err_Ok;
 
711
 
 
712
  FT_Outline       outline;
 
713
  HB_GPOSHeader*  gpos = gpi->gpos;
 
714
  FT_UShort        ap;
 
715
 
 
716
  FT_Short         pixel_value;
 
717
  FT_UShort        load_flags;
 
718
 
 
719
  FT_UShort        x_ppem, y_ppem;
 
720
  FT_Fixed         x_scale, y_scale;
 
721
 
 
722
 
 
723
  x_ppem  = gpi->face->size->metrics.x_ppem;
 
724
  y_ppem  = gpi->face->size->metrics.y_ppem;
 
725
  x_scale = gpi->face->size->metrics.x_scale;
 
726
  y_scale = gpi->face->size->metrics.y_scale;
 
727
 
 
728
  switch ( an->PosFormat )
 
729
  {
 
730
  case 0:
 
731
    /* The special case of an empty AnchorTable */
 
732
 
 
733
    return HB_Err_Not_Covered;
 
734
 
 
735
  case 1:
 
736
    *x_value = x_scale * an->af.af1.XCoordinate / 0x10000;
 
737
    *y_value = y_scale * an->af.af1.YCoordinate / 0x10000;
 
738
    break;
 
739
 
 
740
  case 2:
 
741
    /* glyphs must be scaled */
 
742
 
 
743
    load_flags = gpi->load_flags & ~FT_LOAD_NO_SCALE;
 
744
 
 
745
    if ( !gpi->dvi )
 
746
    {
 
747
      error = (gpos->gfunc)( gpi->face, glyph_index, load_flags );
 
748
      if ( error )
 
749
        return error;
 
750
 
 
751
      if ( gpi->face->glyph->format != ft_glyph_format_outline )
 
752
        return HB_Err_Invalid_GPOS_SubTable;
 
753
 
 
754
      ap = an->af.af2.AnchorPoint;
 
755
 
 
756
      outline = gpi->face->glyph->outline;
 
757
 
 
758
      /* if outline.n_points is set to zero by gfunc(), we use the
 
759
         design coordinate value pair.  This can happen e.g. for
 
760
         sbit glyphs                                               */
 
761
 
 
762
      if ( !outline.n_points )
 
763
        goto no_contour_point;
 
764
 
 
765
      if ( ap >= outline.n_points )
 
766
        return HB_Err_Invalid_GPOS_SubTable;
 
767
 
 
768
      *x_value = outline.points[ap].x;
 
769
      *y_value = outline.points[ap].y;
 
770
    }
 
771
    else
 
772
    {
 
773
    no_contour_point:
 
774
      *x_value = x_scale * an->af.af3.XCoordinate / 0x10000;
 
775
      *y_value = y_scale * an->af.af3.YCoordinate / 0x10000;
 
776
    }
 
777
    break;
 
778
 
 
779
  case 3:
 
780
    if ( !gpi->dvi )
 
781
    {
 
782
      _HB_OPEN_Get_Device( &an->af.af3.XDeviceTable, x_ppem, &pixel_value );
 
783
      *x_value = pixel_value << 6;
 
784
      _HB_OPEN_Get_Device( &an->af.af3.YDeviceTable, y_ppem, &pixel_value );
 
785
      *y_value = pixel_value << 6;
 
786
    }
 
787
    else
 
788
      *x_value = *y_value = 0;
 
789
 
 
790
    *x_value += x_scale * an->af.af3.XCoordinate / 0x10000;
 
791
    *y_value += y_scale * an->af.af3.YCoordinate / 0x10000;
 
792
    break;
 
793
 
 
794
  case 4:
 
795
    error = (gpos->mmfunc)( gpi->face, an->af.af4.XIdAnchor,
 
796
                            x_value, gpos->data );
 
797
    if ( error )
 
798
      return error;
 
799
 
 
800
    error = (gpos->mmfunc)( gpi->face, an->af.af4.YIdAnchor,
 
801
                            y_value, gpos->data );
 
802
    if ( error )
 
803
      return error;
 
804
    break;
 
805
  }
 
806
 
 
807
  return error;
 
808
}
 
809
 
 
810
 
 
811
/* MarkArray */
 
812
 
 
813
static FT_Error  Load_MarkArray ( HB_MarkArray*  ma,
 
814
                                  FT_Stream       stream )
 
815
{
 
816
  FT_Error  error;
 
817
  FT_Memory memory = stream->memory;
 
818
 
 
819
  FT_UShort        n, m, count;
 
820
  FT_ULong         cur_offset, new_offset, base_offset;
 
821
 
 
822
  HB_MarkRecord*  mr;
 
823
 
 
824
 
 
825
  base_offset = FILE_Pos();
 
826
 
 
827
  if ( ACCESS_Frame( 2L ) )
 
828
    return error;
 
829
 
 
830
  count = ma->MarkCount = GET_UShort();
 
831
 
 
832
  FORGET_Frame();
 
833
 
 
834
  ma->MarkRecord = NULL;
 
835
 
 
836
  if ( ALLOC_ARRAY( ma->MarkRecord, count, HB_MarkRecord ) )
 
837
    return error;
 
838
 
 
839
  mr = ma->MarkRecord;
 
840
 
 
841
  for ( n = 0; n < count; n++ )
 
842
  {
 
843
    if ( ACCESS_Frame( 4L ) )
 
844
      goto Fail;
 
845
 
 
846
    mr[n].Class = GET_UShort();
 
847
    new_offset  = GET_UShort() + base_offset;
 
848
 
 
849
    FORGET_Frame();
 
850
 
 
851
    cur_offset = FILE_Pos();
 
852
    if ( FILE_Seek( new_offset ) ||
 
853
         ( error = Load_Anchor( &mr[n].MarkAnchor, stream ) ) != FT_Err_Ok )
 
854
      goto Fail;
 
855
    (void)FILE_Seek( cur_offset );
 
856
  }
 
857
 
 
858
  return FT_Err_Ok;
 
859
 
 
860
Fail:
 
861
  for ( m = 0; m < n; m++ )
 
862
    Free_Anchor( &mr[m].MarkAnchor, memory );
 
863
 
 
864
  FREE( mr );
 
865
  return error;
 
866
}
 
867
 
 
868
 
 
869
static void  Free_MarkArray( HB_MarkArray*  ma,
 
870
                             FT_Memory       memory )
 
871
{
 
872
  FT_UShort        n, count;
 
873
 
 
874
  HB_MarkRecord*  mr;
 
875
 
 
876
 
 
877
  if ( ma->MarkRecord )
 
878
  {
 
879
    count = ma->MarkCount;
 
880
    mr    = ma->MarkRecord;
 
881
 
 
882
    for ( n = 0; n < count; n++ )
 
883
      Free_Anchor( &mr[n].MarkAnchor, memory );
 
884
 
 
885
    FREE( mr );
 
886
  }
 
887
}
 
888
 
 
889
 
 
890
/* LookupType 1 */
 
891
 
 
892
/* SinglePosFormat1 */
 
893
/* SinglePosFormat2 */
 
894
 
 
895
static FT_Error  Load_SinglePos( HB_GPOS_SubTable* st,
 
896
                                 FT_Stream       stream )
 
897
{
 
898
  FT_Error  error;
 
899
  FT_Memory memory = stream->memory;
 
900
  HB_SinglePos*   sp = &st->single;
 
901
 
 
902
  FT_UShort         n, m, count, format;
 
903
  FT_ULong          cur_offset, new_offset, base_offset;
 
904
 
 
905
  HB_ValueRecord*  vr;
 
906
 
 
907
 
 
908
  base_offset = FILE_Pos();
 
909
 
 
910
  if ( ACCESS_Frame( 6L ) )
 
911
    return error;
 
912
 
 
913
  sp->PosFormat = GET_UShort();
 
914
  new_offset    = GET_UShort() + base_offset;
 
915
 
 
916
  format = sp->ValueFormat = GET_UShort();
 
917
 
 
918
  FORGET_Frame();
 
919
 
 
920
  if ( !format )
 
921
    return HB_Err_Invalid_GPOS_SubTable;
 
922
 
 
923
  cur_offset = FILE_Pos();
 
924
  if ( FILE_Seek( new_offset ) ||
 
925
       ( error = _HB_OPEN_Load_Coverage( &sp->Coverage, stream ) ) != FT_Err_Ok )
 
926
    return error;
 
927
  (void)FILE_Seek( cur_offset );
 
928
 
 
929
  switch ( sp->PosFormat )
 
930
  {
 
931
  case 1:
 
932
    error = Load_ValueRecord( &sp->spf.spf1.Value, format,
 
933
                              base_offset, stream );
 
934
    if ( error )
 
935
      goto Fail2;
 
936
    break;
 
937
 
 
938
  case 2:
 
939
    if ( ACCESS_Frame( 2L ) )
 
940
      goto Fail2;
 
941
 
 
942
    count = sp->spf.spf2.ValueCount = GET_UShort();
 
943
 
 
944
    FORGET_Frame();
 
945
 
 
946
    sp->spf.spf2.Value = NULL;
 
947
 
 
948
    if ( ALLOC_ARRAY( sp->spf.spf2.Value, count, HB_ValueRecord ) )
 
949
      goto Fail2;
 
950
 
 
951
    vr = sp->spf.spf2.Value;
 
952
 
 
953
    for ( n = 0; n < count; n++ )
 
954
    {
 
955
      error = Load_ValueRecord( &vr[n], format, base_offset, stream );
 
956
      if ( error )
 
957
        goto Fail1;
 
958
    }
 
959
    break;
 
960
 
 
961
  default:
 
962
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
963
  }
 
964
 
 
965
  return FT_Err_Ok;
 
966
 
 
967
Fail1:
 
968
  for ( m = 0; m < n; m++ )
 
969
    Free_ValueRecord( &vr[m], format, memory );
 
970
 
 
971
  FREE( vr );
 
972
 
 
973
Fail2:
 
974
  _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
 
975
  return error;
 
976
}
 
977
 
 
978
 
 
979
static void  Free_SinglePos( HB_GPOS_SubTable* st,
 
980
                             FT_Memory       memory )
 
981
{
 
982
  FT_UShort         n, count, format;
 
983
  HB_SinglePos*   sp = &st->single;
 
984
 
 
985
  HB_ValueRecord*  v;
 
986
 
 
987
 
 
988
  format = sp->ValueFormat;
 
989
 
 
990
  switch ( sp->PosFormat )
 
991
  {
 
992
  case 1:
 
993
    Free_ValueRecord( &sp->spf.spf1.Value, format, memory );
 
994
    break;
 
995
 
 
996
  case 2:
 
997
    if ( sp->spf.spf2.Value )
 
998
    {
 
999
      count = sp->spf.spf2.ValueCount;
 
1000
      v     = sp->spf.spf2.Value;
 
1001
 
 
1002
      for ( n = 0; n < count; n++ )
 
1003
        Free_ValueRecord( &v[n], format, memory );
 
1004
 
 
1005
      FREE( v );
 
1006
    }
 
1007
    break;
 
1008
  }
 
1009
 
 
1010
  _HB_OPEN_Free_Coverage( &sp->Coverage, memory );
 
1011
}
 
1012
 
 
1013
static FT_Error  Lookup_DefaultPos(  GPOS_Instance*    gpi,
 
1014
                                     HB_GPOS_SubTable* st,
 
1015
                                     HB_Buffer        buffer,
 
1016
                                     FT_UShort         flags,
 
1017
                                     FT_UShort         context_length,
 
1018
                                     int               nesting_level )
 
1019
{
 
1020
  FT_UNUSED(gpi);
 
1021
  FT_UNUSED(st);
 
1022
  FT_UNUSED(buffer);
 
1023
  FT_UNUSED(flags);
 
1024
  FT_UNUSED(context_length);
 
1025
  FT_UNUSED(nesting_level);
 
1026
  return HB_Err_Not_Covered;
 
1027
}
 
1028
 
 
1029
static FT_Error  Lookup_SinglePos( GPOS_Instance*    gpi,
 
1030
                                   HB_GPOS_SubTable* st,
 
1031
                                   HB_Buffer        buffer,
 
1032
                                   FT_UShort         flags,
 
1033
                                   FT_UShort         context_length,
 
1034
                                   int               nesting_level )
 
1035
{
 
1036
  FT_UShort        index, property;
 
1037
  FT_Error         error;
 
1038
  HB_GPOSHeader*  gpos = gpi->gpos;
 
1039
  HB_SinglePos*   sp = &st->single;
 
1040
 
 
1041
  FT_UNUSED(nesting_level);
 
1042
 
 
1043
  if ( context_length != 0xFFFF && context_length < 1 )
 
1044
    return HB_Err_Not_Covered;
 
1045
 
 
1046
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
 
1047
    return error;
 
1048
 
 
1049
  error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
 
1050
  if ( error )
 
1051
    return error;
 
1052
 
 
1053
  switch ( sp->PosFormat )
 
1054
  {
 
1055
  case 1:
 
1056
    error = Get_ValueRecord( gpi, &sp->spf.spf1.Value,
 
1057
                             sp->ValueFormat, POSITION( buffer->in_pos ) );
 
1058
    if ( error )
 
1059
      return error;
 
1060
    break;
 
1061
 
 
1062
  case 2:
 
1063
    if ( index >= sp->spf.spf2.ValueCount )
 
1064
      return HB_Err_Invalid_GPOS_SubTable;
 
1065
    error = Get_ValueRecord( gpi, &sp->spf.spf2.Value[index],
 
1066
                             sp->ValueFormat, POSITION( buffer->in_pos ) );
 
1067
    if ( error )
 
1068
      return error;
 
1069
    break;
 
1070
 
 
1071
  default:
 
1072
    return HB_Err_Invalid_GPOS_SubTable;
 
1073
  }
 
1074
 
 
1075
  (buffer->in_pos)++;
 
1076
 
 
1077
  return FT_Err_Ok;
 
1078
}
 
1079
 
 
1080
 
 
1081
/* LookupType 2 */
 
1082
 
 
1083
/* PairSet */
 
1084
 
 
1085
static FT_Error  Load_PairSet ( HB_PairSet*  ps,
 
1086
                                FT_UShort     format1,
 
1087
                                FT_UShort     format2,
 
1088
                                FT_Stream     stream )
 
1089
{
 
1090
  FT_Error  error;
 
1091
  FT_Memory memory = stream->memory;
 
1092
 
 
1093
  FT_UShort             n, m, count;
 
1094
  FT_ULong              base_offset;
 
1095
 
 
1096
  HB_PairValueRecord*  pvr;
 
1097
 
 
1098
 
 
1099
  base_offset = FILE_Pos();
 
1100
 
 
1101
  if ( ACCESS_Frame( 2L ) )
 
1102
    return error;
 
1103
 
 
1104
  count = ps->PairValueCount = GET_UShort();
 
1105
 
 
1106
  FORGET_Frame();
 
1107
 
 
1108
  ps->PairValueRecord = NULL;
 
1109
 
 
1110
  if ( ALLOC_ARRAY( ps->PairValueRecord, count, HB_PairValueRecord ) )
 
1111
    return error;
 
1112
 
 
1113
  pvr = ps->PairValueRecord;
 
1114
 
 
1115
  for ( n = 0; n < count; n++ )
 
1116
  {
 
1117
    if ( ACCESS_Frame( 2L ) )
 
1118
      goto Fail;
 
1119
 
 
1120
    pvr[n].SecondGlyph = GET_UShort();
 
1121
 
 
1122
    FORGET_Frame();
 
1123
 
 
1124
    if ( format1 )
 
1125
    {
 
1126
      error = Load_ValueRecord( &pvr[n].Value1, format1,
 
1127
                                base_offset, stream );
 
1128
      if ( error )
 
1129
        goto Fail;
 
1130
    }
 
1131
    if ( format2 )
 
1132
    {
 
1133
      error = Load_ValueRecord( &pvr[n].Value2, format2,
 
1134
                                base_offset, stream );
 
1135
      if ( error )
 
1136
      {
 
1137
        if ( format1 )
 
1138
          Free_ValueRecord( &pvr[n].Value1, format1, memory );
 
1139
        goto Fail;
 
1140
      }
 
1141
    }
 
1142
  }
 
1143
 
 
1144
  return FT_Err_Ok;
 
1145
 
 
1146
Fail:
 
1147
  for ( m = 0; m < n; m++ )
 
1148
  {
 
1149
    if ( format1 )
 
1150
      Free_ValueRecord( &pvr[m].Value1, format1, memory );
 
1151
    if ( format2 )
 
1152
      Free_ValueRecord( &pvr[m].Value2, format2, memory );
 
1153
  }
 
1154
 
 
1155
  FREE( pvr );
 
1156
  return error;
 
1157
}
 
1158
 
 
1159
 
 
1160
static void  Free_PairSet( HB_PairSet*  ps,
 
1161
                           FT_UShort     format1,
 
1162
                           FT_UShort     format2,
 
1163
                           FT_Memory     memory )
 
1164
{
 
1165
  FT_UShort             n, count;
 
1166
 
 
1167
  HB_PairValueRecord*  pvr;
 
1168
 
 
1169
 
 
1170
  if ( ps->PairValueRecord )
 
1171
  {
 
1172
    count = ps->PairValueCount;
 
1173
    pvr   = ps->PairValueRecord;
 
1174
 
 
1175
    for ( n = 0; n < count; n++ )
 
1176
    {
 
1177
      if ( format1 )
 
1178
        Free_ValueRecord( &pvr[n].Value1, format1, memory );
 
1179
      if ( format2 )
 
1180
        Free_ValueRecord( &pvr[n].Value2, format2, memory );
 
1181
    }
 
1182
 
 
1183
    FREE( pvr );
 
1184
  }
 
1185
}
 
1186
 
 
1187
 
 
1188
/* PairPosFormat1 */
 
1189
 
 
1190
static FT_Error  Load_PairPos1( HB_PairPosFormat1*  ppf1,
 
1191
                                FT_UShort            format1,
 
1192
                                FT_UShort            format2,
 
1193
                                FT_Stream            stream )
 
1194
{
 
1195
  FT_Error  error;
 
1196
  FT_Memory memory = stream->memory;
 
1197
 
 
1198
  FT_UShort     n, m, count;
 
1199
  FT_ULong      cur_offset, new_offset, base_offset;
 
1200
 
 
1201
  HB_PairSet*  ps;
 
1202
 
 
1203
 
 
1204
  base_offset = FILE_Pos() - 8L;
 
1205
 
 
1206
  if ( ACCESS_Frame( 2L ) )
 
1207
    return error;
 
1208
 
 
1209
  count = ppf1->PairSetCount = GET_UShort();
 
1210
 
 
1211
  FORGET_Frame();
 
1212
 
 
1213
  ppf1->PairSet = NULL;
 
1214
 
 
1215
  if ( ALLOC_ARRAY( ppf1->PairSet, count, HB_PairSet ) )
 
1216
    return error;
 
1217
 
 
1218
  ps = ppf1->PairSet;
 
1219
 
 
1220
  for ( n = 0; n < count; n++ )
 
1221
  {
 
1222
    if ( ACCESS_Frame( 2L ) )
 
1223
      goto Fail;
 
1224
 
 
1225
    new_offset = GET_UShort() + base_offset;
 
1226
 
 
1227
    FORGET_Frame();
 
1228
 
 
1229
    cur_offset = FILE_Pos();
 
1230
    if ( FILE_Seek( new_offset ) ||
 
1231
         ( error = Load_PairSet( &ps[n], format1,
 
1232
                                 format2, stream ) ) != FT_Err_Ok )
 
1233
      goto Fail;
 
1234
    (void)FILE_Seek( cur_offset );
 
1235
  }
 
1236
 
 
1237
  return FT_Err_Ok;
 
1238
 
 
1239
Fail:
 
1240
  for ( m = 0; m < n; m++ )
 
1241
    Free_PairSet( &ps[m], format1, format2, memory );
 
1242
 
 
1243
  FREE( ps );
 
1244
  return error;
 
1245
}
 
1246
 
 
1247
 
 
1248
static void  Free_PairPos1( HB_PairPosFormat1*  ppf1,
 
1249
                            FT_UShort            format1,
 
1250
                            FT_UShort            format2,
 
1251
                            FT_Memory            memory )
 
1252
{
 
1253
  FT_UShort     n, count;
 
1254
 
 
1255
  HB_PairSet*  ps;
 
1256
 
 
1257
 
 
1258
  if ( ppf1->PairSet )
 
1259
  {
 
1260
    count = ppf1->PairSetCount;
 
1261
    ps    = ppf1->PairSet;
 
1262
 
 
1263
    for ( n = 0; n < count; n++ )
 
1264
      Free_PairSet( &ps[n], format1, format2, memory );
 
1265
 
 
1266
    FREE( ps );
 
1267
  }
 
1268
}
 
1269
 
 
1270
 
 
1271
/* PairPosFormat2 */
 
1272
 
 
1273
static FT_Error  Load_PairPos2( HB_PairPosFormat2*  ppf2,
 
1274
                                FT_UShort            format1,
 
1275
                                FT_UShort            format2,
 
1276
                                FT_Stream            stream )
 
1277
{
 
1278
  FT_Error  error;
 
1279
  FT_Memory memory = stream->memory;
 
1280
 
 
1281
  FT_UShort          m, n, k, count1, count2;
 
1282
  FT_ULong           cur_offset, new_offset1, new_offset2, base_offset;
 
1283
 
 
1284
  HB_Class1Record*  c1r;
 
1285
  HB_Class2Record*  c2r;
 
1286
 
 
1287
 
 
1288
  base_offset = FILE_Pos() - 8L;
 
1289
 
 
1290
  if ( ACCESS_Frame( 8L ) )
 
1291
    return error;
 
1292
 
 
1293
  new_offset1 = GET_UShort() + base_offset;
 
1294
  new_offset2 = GET_UShort() + base_offset;
 
1295
 
 
1296
  /* `Class1Count' and `Class2Count' are the upper limits for class
 
1297
     values, thus we read it now to make additional safety checks.  */
 
1298
 
 
1299
  count1 = ppf2->Class1Count = GET_UShort();
 
1300
  count2 = ppf2->Class2Count = GET_UShort();
 
1301
 
 
1302
  FORGET_Frame();
 
1303
 
 
1304
  cur_offset = FILE_Pos();
 
1305
  if ( FILE_Seek( new_offset1 ) ||
 
1306
       ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef1, count1,
 
1307
                                       stream ) ) != FT_Err_Ok )
 
1308
    return error;
 
1309
  if ( FILE_Seek( new_offset2 ) ||
 
1310
       ( error = _HB_OPEN_Load_ClassDefinition( &ppf2->ClassDef2, count2,
 
1311
                                       stream ) ) != FT_Err_Ok )
 
1312
    goto Fail3;
 
1313
  (void)FILE_Seek( cur_offset );
 
1314
 
 
1315
  ppf2->Class1Record = NULL;
 
1316
 
 
1317
  if ( ALLOC_ARRAY( ppf2->Class1Record, count1, HB_Class1Record ) )
 
1318
    goto Fail2;
 
1319
 
 
1320
  c1r = ppf2->Class1Record;
 
1321
 
 
1322
  for ( m = 0; m < count1; m++ )
 
1323
  {
 
1324
    c1r[m].Class2Record = NULL;
 
1325
 
 
1326
    if ( ALLOC_ARRAY( c1r[m].Class2Record, count2, HB_Class2Record ) )
 
1327
      goto Fail1;
 
1328
 
 
1329
    c2r = c1r[m].Class2Record;
 
1330
 
 
1331
    for ( n = 0; n < count2; n++ )
 
1332
    {
 
1333
      if ( format1 )
 
1334
      {
 
1335
        error = Load_ValueRecord( &c2r[n].Value1, format1,
 
1336
                                  base_offset, stream );
 
1337
        if ( error )
 
1338
          goto Fail0;
 
1339
      }
 
1340
      if ( format2 )
 
1341
      {
 
1342
        error = Load_ValueRecord( &c2r[n].Value2, format2,
 
1343
                                  base_offset, stream );
 
1344
        if ( error )
 
1345
        {
 
1346
          if ( format1 )
 
1347
            Free_ValueRecord( &c2r[n].Value1, format1, memory );
 
1348
          goto Fail0;
 
1349
        }
 
1350
      }
 
1351
    }
 
1352
 
 
1353
    continue;
 
1354
 
 
1355
  Fail0:
 
1356
    for ( k = 0; k < n; k++ )
 
1357
    {
 
1358
      if ( format1 )
 
1359
        Free_ValueRecord( &c2r[k].Value1, format1, memory );
 
1360
      if ( format2 )
 
1361
        Free_ValueRecord( &c2r[k].Value2, format2, memory );
 
1362
    }
 
1363
    goto Fail1;
 
1364
  }
 
1365
 
 
1366
  return FT_Err_Ok;
 
1367
 
 
1368
Fail1:
 
1369
  for ( k = 0; k < m; k++ )
 
1370
  {
 
1371
    c2r = c1r[k].Class2Record;
 
1372
 
 
1373
    for ( n = 0; n < count2; n++ )
 
1374
    {
 
1375
      if ( format1 )
 
1376
        Free_ValueRecord( &c2r[n].Value1, format1, memory );
 
1377
      if ( format2 )
 
1378
        Free_ValueRecord( &c2r[n].Value2, format2, memory );
 
1379
    }
 
1380
 
 
1381
    FREE( c2r );
 
1382
  }
 
1383
 
 
1384
  FREE( c1r );
 
1385
Fail2:
 
1386
 
 
1387
  _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
 
1388
 
 
1389
Fail3:
 
1390
  _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
 
1391
  return error;
 
1392
}
 
1393
 
 
1394
 
 
1395
static void  Free_PairPos2( HB_PairPosFormat2*  ppf2,
 
1396
                            FT_UShort            format1,
 
1397
                            FT_UShort            format2,
 
1398
                            FT_Memory            memory )
 
1399
{
 
1400
  FT_UShort          m, n, count1, count2;
 
1401
 
 
1402
  HB_Class1Record*  c1r;
 
1403
  HB_Class2Record*  c2r;
 
1404
 
 
1405
 
 
1406
  if ( ppf2->Class1Record )
 
1407
  {
 
1408
    c1r    = ppf2->Class1Record;
 
1409
    count1 = ppf2->Class1Count;
 
1410
    count2 = ppf2->Class2Count;
 
1411
 
 
1412
    for ( m = 0; m < count1; m++ )
 
1413
    {
 
1414
      c2r = c1r[m].Class2Record;
 
1415
 
 
1416
      for ( n = 0; n < count2; n++ )
 
1417
      {
 
1418
        if ( format1 )
 
1419
          Free_ValueRecord( &c2r[n].Value1, format1, memory );
 
1420
        if ( format2 )
 
1421
          Free_ValueRecord( &c2r[n].Value2, format2, memory );
 
1422
      }
 
1423
 
 
1424
      FREE( c2r );
 
1425
    }
 
1426
 
 
1427
    FREE( c1r );
 
1428
 
 
1429
    _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef2, memory );
 
1430
    _HB_OPEN_Free_ClassDefinition( &ppf2->ClassDef1, memory );
 
1431
  }
 
1432
}
 
1433
 
 
1434
 
 
1435
static FT_Error  Load_PairPos( HB_GPOS_SubTable* st,
 
1436
                               FT_Stream     stream )
 
1437
{
 
1438
  FT_Error  error;
 
1439
  FT_Memory memory = stream->memory;
 
1440
  HB_PairPos*     pp = &st->pair;
 
1441
 
 
1442
  FT_UShort         format1, format2;
 
1443
  FT_ULong          cur_offset, new_offset, base_offset;
 
1444
 
 
1445
 
 
1446
  base_offset = FILE_Pos();
 
1447
 
 
1448
  if ( ACCESS_Frame( 8L ) )
 
1449
    return error;
 
1450
 
 
1451
  pp->PosFormat = GET_UShort();
 
1452
  new_offset    = GET_UShort() + base_offset;
 
1453
 
 
1454
  format1 = pp->ValueFormat1 = GET_UShort();
 
1455
  format2 = pp->ValueFormat2 = GET_UShort();
 
1456
 
 
1457
  FORGET_Frame();
 
1458
 
 
1459
  cur_offset = FILE_Pos();
 
1460
  if ( FILE_Seek( new_offset ) ||
 
1461
       ( error = _HB_OPEN_Load_Coverage( &pp->Coverage, stream ) ) != FT_Err_Ok )
 
1462
    return error;
 
1463
  (void)FILE_Seek( cur_offset );
 
1464
 
 
1465
  switch ( pp->PosFormat )
 
1466
  {
 
1467
  case 1:
 
1468
    error = Load_PairPos1( &pp->ppf.ppf1, format1, format2, stream );
 
1469
    if ( error )
 
1470
      goto Fail;
 
1471
    break;
 
1472
 
 
1473
  case 2:
 
1474
    error = Load_PairPos2( &pp->ppf.ppf2, format1, format2, stream );
 
1475
    if ( error )
 
1476
      goto Fail;
 
1477
    break;
 
1478
 
 
1479
  default:
 
1480
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
1481
  }
 
1482
 
 
1483
  return FT_Err_Ok;
 
1484
 
 
1485
Fail:
 
1486
  _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
 
1487
  return error;
 
1488
}
 
1489
 
 
1490
 
 
1491
static void  Free_PairPos( HB_GPOS_SubTable* st,
 
1492
                           FT_Memory     memory )
 
1493
{
 
1494
  FT_UShort  format1, format2;
 
1495
  HB_PairPos*     pp = &st->pair;
 
1496
 
 
1497
 
 
1498
  format1 = pp->ValueFormat1;
 
1499
  format2 = pp->ValueFormat2;
 
1500
 
 
1501
  switch ( pp->PosFormat )
 
1502
  {
 
1503
  case 1:
 
1504
    Free_PairPos1( &pp->ppf.ppf1, format1, format2, memory );
 
1505
    break;
 
1506
 
 
1507
  case 2:
 
1508
    Free_PairPos2( &pp->ppf.ppf2, format1, format2, memory );
 
1509
    break;
 
1510
  }
 
1511
 
 
1512
  _HB_OPEN_Free_Coverage( &pp->Coverage, memory );
 
1513
}
 
1514
 
 
1515
 
 
1516
static FT_Error  Lookup_PairPos1( GPOS_Instance*       gpi,
 
1517
                                  HB_PairPosFormat1*  ppf1,
 
1518
                                  HB_Buffer           buffer,
 
1519
                                  FT_UShort            first_pos,
 
1520
                                  FT_UShort            index,
 
1521
                                  FT_UShort            format1,
 
1522
                                  FT_UShort            format2 )
 
1523
{
 
1524
  FT_Error              error;
 
1525
  FT_UShort             numpvr, glyph2;
 
1526
 
 
1527
  HB_PairValueRecord*  pvr;
 
1528
 
 
1529
 
 
1530
  if ( index >= ppf1->PairSetCount )
 
1531
     return HB_Err_Invalid_GPOS_SubTable;
 
1532
 
 
1533
  pvr = ppf1->PairSet[index].PairValueRecord;
 
1534
  if ( !pvr )
 
1535
    return HB_Err_Invalid_GPOS_SubTable;
 
1536
 
 
1537
  glyph2 = IN_CURGLYPH();
 
1538
 
 
1539
  for ( numpvr = ppf1->PairSet[index].PairValueCount;
 
1540
        numpvr;
 
1541
        numpvr--, pvr++ )
 
1542
  {
 
1543
    if ( glyph2 == pvr->SecondGlyph )
 
1544
    {
 
1545
      error = Get_ValueRecord( gpi, &pvr->Value1, format1,
 
1546
                               POSITION( first_pos ) );
 
1547
      if ( error )
 
1548
        return error;
 
1549
      return Get_ValueRecord( gpi, &pvr->Value2, format2,
 
1550
                              POSITION( buffer->in_pos ) );
 
1551
    }
 
1552
  }
 
1553
 
 
1554
  return HB_Err_Not_Covered;
 
1555
}
 
1556
 
 
1557
 
 
1558
static FT_Error  Lookup_PairPos2( GPOS_Instance*       gpi,
 
1559
                                  HB_PairPosFormat2*  ppf2,
 
1560
                                  HB_Buffer           buffer,
 
1561
                                  FT_UShort            first_pos,
 
1562
                                  FT_UShort            format1,
 
1563
                                  FT_UShort            format2 )
 
1564
{
 
1565
  FT_Error           error;
 
1566
  FT_UShort          cl1, cl2;
 
1567
 
 
1568
  HB_Class1Record*  c1r;
 
1569
  HB_Class2Record*  c2r;
 
1570
 
 
1571
 
 
1572
  error = _HB_OPEN_Get_Class( &ppf2->ClassDef1, IN_GLYPH( first_pos ),
 
1573
                     &cl1, NULL );
 
1574
  if ( error && error != HB_Err_Not_Covered )
 
1575
    return error;
 
1576
  error = _HB_OPEN_Get_Class( &ppf2->ClassDef2, IN_CURGLYPH(),
 
1577
                     &cl2, NULL );
 
1578
  if ( error && error != HB_Err_Not_Covered )
 
1579
    return error;
 
1580
 
 
1581
  c1r = &ppf2->Class1Record[cl1];
 
1582
  if ( !c1r )
 
1583
    return HB_Err_Invalid_GPOS_SubTable;
 
1584
  c2r = &c1r->Class2Record[cl2];
 
1585
 
 
1586
  error = Get_ValueRecord( gpi, &c2r->Value1, format1, POSITION( first_pos ) );
 
1587
  if ( error )
 
1588
    return error;
 
1589
  return Get_ValueRecord( gpi, &c2r->Value2, format2, POSITION( buffer->in_pos ) );
 
1590
}
 
1591
 
 
1592
 
 
1593
static FT_Error  Lookup_PairPos( GPOS_Instance*    gpi,
 
1594
                                 HB_GPOS_SubTable* st,
 
1595
                                 HB_Buffer        buffer,
 
1596
                                 FT_UShort         flags,
 
1597
                                 FT_UShort         context_length,
 
1598
                                 int               nesting_level )
 
1599
{
 
1600
  FT_Error         error;
 
1601
  FT_UShort        index, property, first_pos;
 
1602
  HB_GPOSHeader*  gpos = gpi->gpos;
 
1603
  HB_PairPos*     pp = &st->pair;
 
1604
 
 
1605
  FT_UNUSED(nesting_level);
 
1606
 
 
1607
  if ( buffer->in_pos >= buffer->in_length - 1 )
 
1608
    return HB_Err_Not_Covered;           /* Not enough glyphs in stream */
 
1609
 
 
1610
  if ( context_length != 0xFFFF && context_length < 2 )
 
1611
    return HB_Err_Not_Covered;
 
1612
 
 
1613
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
 
1614
    return error;
 
1615
 
 
1616
  error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
 
1617
  if ( error )
 
1618
    return error;
 
1619
 
 
1620
  /* second glyph */
 
1621
 
 
1622
  first_pos = buffer->in_pos;
 
1623
  (buffer->in_pos)++;
 
1624
 
 
1625
  while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
 
1626
                          flags, &property ) )
 
1627
  {
 
1628
    if ( error && error != HB_Err_Not_Covered )
 
1629
      return error;
 
1630
 
 
1631
    if ( buffer->in_pos == buffer->in_length )
 
1632
      return HB_Err_Not_Covered;
 
1633
    (buffer->in_pos)++;
 
1634
  }
 
1635
 
 
1636
  switch ( pp->PosFormat )
 
1637
  {
 
1638
  case 1:
 
1639
    error = Lookup_PairPos1( gpi, &pp->ppf.ppf1, buffer,
 
1640
                             first_pos, index,
 
1641
                             pp->ValueFormat1, pp->ValueFormat2 );
 
1642
    break;
 
1643
 
 
1644
  case 2:
 
1645
    error = Lookup_PairPos2( gpi, &pp->ppf.ppf2, buffer, first_pos,
 
1646
                             pp->ValueFormat1, pp->ValueFormat2 );
 
1647
    break;
 
1648
 
 
1649
  default:
 
1650
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
1651
  }
 
1652
 
 
1653
  /* adjusting the `next' glyph */
 
1654
 
 
1655
  if ( pp->ValueFormat2 )
 
1656
    (buffer->in_pos)++;
 
1657
 
 
1658
  return error;
 
1659
}
 
1660
 
 
1661
 
 
1662
/* LookupType 3 */
 
1663
 
 
1664
/* CursivePosFormat1 */
 
1665
 
 
1666
static FT_Error  Load_CursivePos( HB_GPOS_SubTable* st,
 
1667
                                  FT_Stream        stream )
 
1668
{
 
1669
  FT_Error  error;
 
1670
  FT_Memory memory = stream->memory;
 
1671
  HB_CursivePos*  cp = &st->cursive;
 
1672
 
 
1673
  FT_UShort             n, m, count;
 
1674
  FT_ULong              cur_offset, new_offset, base_offset;
 
1675
 
 
1676
  HB_EntryExitRecord*  eer;
 
1677
 
 
1678
 
 
1679
  base_offset = FILE_Pos();
 
1680
 
 
1681
  if ( ACCESS_Frame( 4L ) )
 
1682
    return error;
 
1683
 
 
1684
  cp->PosFormat = GET_UShort();
 
1685
  new_offset    = GET_UShort() + base_offset;
 
1686
 
 
1687
  FORGET_Frame();
 
1688
 
 
1689
  cur_offset = FILE_Pos();
 
1690
  if ( FILE_Seek( new_offset ) ||
 
1691
       ( error = _HB_OPEN_Load_Coverage( &cp->Coverage, stream ) ) != FT_Err_Ok )
 
1692
    return error;
 
1693
  (void)FILE_Seek( cur_offset );
 
1694
 
 
1695
  if ( ACCESS_Frame( 2L ) )
 
1696
    goto Fail2;
 
1697
 
 
1698
  count = cp->EntryExitCount = GET_UShort();
 
1699
 
 
1700
  FORGET_Frame();
 
1701
 
 
1702
  cp->EntryExitRecord = NULL;
 
1703
 
 
1704
  if ( ALLOC_ARRAY( cp->EntryExitRecord, count, HB_EntryExitRecord ) )
 
1705
    goto Fail2;
 
1706
 
 
1707
  eer = cp->EntryExitRecord;
 
1708
 
 
1709
  for ( n = 0; n < count; n++ )
 
1710
  {
 
1711
    FT_ULong entry_offset;
 
1712
 
 
1713
    if ( ACCESS_Frame( 2L ) )
 
1714
      return error;
 
1715
 
 
1716
    entry_offset = new_offset = GET_UShort();
 
1717
 
 
1718
    FORGET_Frame();
 
1719
 
 
1720
    if ( new_offset )
 
1721
    {
 
1722
      new_offset += base_offset;
 
1723
 
 
1724
      cur_offset = FILE_Pos();
 
1725
      if ( FILE_Seek( new_offset ) ||
 
1726
           ( error = Load_Anchor( &eer[n].EntryAnchor,
 
1727
                                  stream ) ) != FT_Err_Ok )
 
1728
        goto Fail1;
 
1729
      (void)FILE_Seek( cur_offset );
 
1730
    }
 
1731
    else
 
1732
      eer[n].EntryAnchor.PosFormat   = 0;
 
1733
 
 
1734
    if ( ACCESS_Frame( 2L ) )
 
1735
      return error;
 
1736
 
 
1737
    new_offset = GET_UShort();
 
1738
 
 
1739
    FORGET_Frame();
 
1740
 
 
1741
    if ( new_offset )
 
1742
    {
 
1743
      new_offset += base_offset;
 
1744
 
 
1745
      cur_offset = FILE_Pos();
 
1746
      if ( FILE_Seek( new_offset ) ||
 
1747
           ( error = Load_Anchor( &eer[n].ExitAnchor,
 
1748
                                  stream ) ) != FT_Err_Ok )
 
1749
      {
 
1750
        if ( entry_offset )
 
1751
          Free_Anchor( &eer[n].EntryAnchor, memory );
 
1752
        goto Fail1;
 
1753
      }
 
1754
      (void)FILE_Seek( cur_offset );
 
1755
    }
 
1756
    else
 
1757
      eer[n].ExitAnchor.PosFormat   = 0;
 
1758
  }
 
1759
 
 
1760
  return FT_Err_Ok;
 
1761
 
 
1762
Fail1:
 
1763
  for ( m = 0; m < n; m++ )
 
1764
  {
 
1765
    Free_Anchor( &eer[m].EntryAnchor, memory );
 
1766
    Free_Anchor( &eer[m].ExitAnchor, memory );
 
1767
  }
 
1768
 
 
1769
  FREE( eer );
 
1770
 
 
1771
Fail2:
 
1772
  _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
 
1773
  return error;
 
1774
}
 
1775
 
 
1776
 
 
1777
static void  Free_CursivePos( HB_GPOS_SubTable* st,
 
1778
                              FT_Memory        memory )
 
1779
{
 
1780
  FT_UShort             n, count;
 
1781
  HB_CursivePos*  cp = &st->cursive;
 
1782
 
 
1783
  HB_EntryExitRecord*  eer;
 
1784
 
 
1785
 
 
1786
  if ( cp->EntryExitRecord )
 
1787
  {
 
1788
    count = cp->EntryExitCount;
 
1789
    eer   = cp->EntryExitRecord;
 
1790
 
 
1791
    for ( n = 0; n < count; n++ )
 
1792
    {
 
1793
      Free_Anchor( &eer[n].EntryAnchor, memory );
 
1794
      Free_Anchor( &eer[n].ExitAnchor, memory );
 
1795
    }
 
1796
 
 
1797
    FREE( eer );
 
1798
  }
 
1799
 
 
1800
  _HB_OPEN_Free_Coverage( &cp->Coverage, memory );
 
1801
}
 
1802
 
 
1803
 
 
1804
static FT_Error  Lookup_CursivePos( GPOS_Instance*    gpi,
 
1805
                                    HB_GPOS_SubTable* st,
 
1806
                                    HB_Buffer        buffer,
 
1807
                                    FT_UShort         flags,
 
1808
                                    FT_UShort         context_length,
 
1809
                                    int               nesting_level )
 
1810
{
 
1811
  FT_UShort        index, property;
 
1812
  FT_Error         error;
 
1813
  HB_GPOSHeader*  gpos = gpi->gpos;
 
1814
  HB_CursivePos*  cp = &st->cursive;
 
1815
 
 
1816
  HB_EntryExitRecord*  eer;
 
1817
  FT_Pos                entry_x, entry_y;
 
1818
  FT_Pos                exit_x, exit_y;
 
1819
 
 
1820
  FT_UNUSED(nesting_level);
 
1821
 
 
1822
  if ( context_length != 0xFFFF && context_length < 1 )
 
1823
  {
 
1824
    gpi->last = 0xFFFF;
 
1825
    return HB_Err_Not_Covered;
 
1826
  }
 
1827
 
 
1828
  /* Glyphs not having the right GDEF properties will be ignored, i.e.,
 
1829
     gpi->last won't be reset (contrary to user defined properties). */
 
1830
 
 
1831
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
 
1832
    return error;
 
1833
 
 
1834
  /* We don't handle mark glyphs here.  According to Andrei, this isn't
 
1835
     possible, but who knows...                                         */
 
1836
 
 
1837
  if ( property == HB_GDEF_MARK )
 
1838
  {
 
1839
    gpi->last = 0xFFFF;
 
1840
    return HB_Err_Not_Covered;
 
1841
  }
 
1842
 
 
1843
  error = _HB_OPEN_Coverage_Index( &cp->Coverage, IN_CURGLYPH(), &index );
 
1844
  if ( error )
 
1845
  {
 
1846
    gpi->last = 0xFFFF;
 
1847
    return error;
 
1848
  }
 
1849
 
 
1850
  if ( index >= cp->EntryExitCount )
 
1851
    return HB_Err_Invalid_GPOS_SubTable;
 
1852
 
 
1853
  eer = &cp->EntryExitRecord[index];
 
1854
 
 
1855
  /* Now comes the messiest part of the whole OpenType
 
1856
     specification.  At first glance, cursive connections seem easy
 
1857
     to understand, but there are pitfalls!  The reason is that
 
1858
     the specs don't mention how to compute the advance values
 
1859
     resp. glyph offsets.  I was told it would be an omission, to
 
1860
     be fixed in the next OpenType version...  Again many thanks to
 
1861
     Andrei Burago <andreib@microsoft.com> for clarifications.
 
1862
 
 
1863
     Consider the following example:
 
1864
 
 
1865
                      |  xadv1    |
 
1866
                       +---------+
 
1867
                       |         |
 
1868
                 +-----+--+ 1    |
 
1869
                 |     | .|      |
 
1870
                 |    0+--+------+
 
1871
                 |   2    |
 
1872
                 |        |
 
1873
                0+--------+
 
1874
                |  xadv2   |
 
1875
 
 
1876
       glyph1: advance width = 12
 
1877
               anchor point = (3,1)
 
1878
 
 
1879
       glyph2: advance width = 11
 
1880
               anchor point = (9,4)
 
1881
 
 
1882
       LSB is 1 for both glyphs (so the boxes drawn above are glyph
 
1883
       bboxes).  Writing direction is R2L; `0' denotes the glyph's
 
1884
       coordinate origin.
 
1885
 
 
1886
     Now the surprising part: The advance width of the *left* glyph
 
1887
     (resp. of the *bottom* glyph) will be modified, no matter
 
1888
     whether the writing direction is L2R or R2L (resp. T2B or
 
1889
     B2T)!  This assymetry is caused by the fact that the glyph's
 
1890
     coordinate origin is always the lower left corner for all
 
1891
     writing directions.
 
1892
 
 
1893
     Continuing the above example, we can compute the new
 
1894
     (horizontal) advance width of glyph2 as
 
1895
 
 
1896
       9 - 3 = 6  ,
 
1897
 
 
1898
     and the new vertical offset of glyph2 as
 
1899
 
 
1900
       1 - 4 = -3  .
 
1901
 
 
1902
 
 
1903
     Vertical writing direction is far more complicated:
 
1904
 
 
1905
     a) Assuming that we recompute the advance height of the lower glyph:
 
1906
 
 
1907
                                  --
 
1908
                       +---------+
 
1909
              --       |         |
 
1910
                 +-----+--+ 1    | yadv1
 
1911
                 |     | .|      |
 
1912
           yadv2 |    0+--+------+        -- BSB1  --
 
1913
                 |   2    |       --      --        y_offset
 
1914
                 |        |
 
1915
   BSB2 --      0+--------+                        --
 
1916
        --    --
 
1917
 
 
1918
       glyph1: advance height = 6
 
1919
               anchor point = (3,1)
 
1920
 
 
1921
       glyph2: advance height = 7
 
1922
               anchor point = (9,4)
 
1923
 
 
1924
       TSB is 1 for both glyphs; writing direction is T2B.
 
1925
 
 
1926
 
 
1927
         BSB1     = yadv1 - (TSB1 + ymax1)
 
1928
         BSB2     = yadv2 - (TSB2 + ymax2)
 
1929
         y_offset = y2 - y1
 
1930
 
 
1931
       vertical advance width of glyph2
 
1932
         = y_offset + BSB2 - BSB1
 
1933
         = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
 
1934
         = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
 
1935
         = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
 
1936
 
 
1937
 
 
1938
     b) Assuming that we recompute the advance height of the upper glyph:
 
1939
 
 
1940
                                  --      --
 
1941
                       +---------+        -- TSB1
 
1942
        --    --       |         |
 
1943
   TSB2 --       +-----+--+ 1    | yadv1   ymax1
 
1944
                 |     | .|      |
 
1945
           yadv2 |    0+--+------+        --       --
 
1946
    ymax2        |   2    |       --                y_offset
 
1947
                 |        |
 
1948
        --      0+--------+                        --
 
1949
              --
 
1950
 
 
1951
       glyph1: advance height = 6
 
1952
               anchor point = (3,1)
 
1953
 
 
1954
       glyph2: advance height = 7
 
1955
               anchor point = (9,4)
 
1956
 
 
1957
       TSB is 1 for both glyphs; writing direction is T2B.
 
1958
 
 
1959
       y_offset = y2 - y1
 
1960
 
 
1961
       vertical advance width of glyph2
 
1962
         = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
 
1963
         = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
 
1964
 
 
1965
 
 
1966
     Comparing a) with b) shows that b) is easier to compute.  I'll wait
 
1967
     for a reply from Andrei to see what should really be implemented...
 
1968
 
 
1969
     Since horizontal advance widths or vertical advance heights
 
1970
     can be used alone but not together, no ambiguity occurs.        */
 
1971
 
 
1972
  if ( gpi->last == 0xFFFF )
 
1973
    goto end;
 
1974
 
 
1975
  /* Get_Anchor() returns HB_Err_Not_Covered if there is no anchor
 
1976
     table.                                                         */
 
1977
 
 
1978
  error = Get_Anchor( gpi, &eer->EntryAnchor, IN_CURGLYPH(),
 
1979
                      &entry_x, &entry_y );
 
1980
  if ( error == HB_Err_Not_Covered )
 
1981
    goto end;
 
1982
  if ( error )
 
1983
    return error;
 
1984
 
 
1985
  if ( gpi->r2l )
 
1986
  {
 
1987
    POSITION( buffer->in_pos )->x_advance   = entry_x - gpi->anchor_x;
 
1988
    POSITION( buffer->in_pos )->new_advance = TRUE;
 
1989
  }
 
1990
  else
 
1991
  {
 
1992
    POSITION( gpi->last )->x_advance   = gpi->anchor_x - entry_x;
 
1993
    POSITION( gpi->last )->new_advance = TRUE;
 
1994
  }
 
1995
 
 
1996
  if ( flags & HB_LOOKUP_FLAG_RIGHT_TO_LEFT )
 
1997
  {
 
1998
    POSITION( gpi->last )->cursive_chain = gpi->last - buffer->in_pos;
 
1999
    POSITION( gpi->last )->y_pos = entry_y - gpi->anchor_y;
 
2000
  }
 
2001
  else
 
2002
  {
 
2003
    POSITION( buffer->in_pos )->cursive_chain = buffer->in_pos - gpi->last;
 
2004
    POSITION( buffer->in_pos )->y_pos = gpi->anchor_y - entry_y;
 
2005
  }
 
2006
 
 
2007
end:
 
2008
  error = Get_Anchor( gpi, &eer->ExitAnchor, IN_CURGLYPH(),
 
2009
                      &exit_x, &exit_y );
 
2010
  if ( error == HB_Err_Not_Covered )
 
2011
    gpi->last = 0xFFFF;
 
2012
  else
 
2013
  {
 
2014
    gpi->last     = buffer->in_pos;
 
2015
    gpi->anchor_x = exit_x;
 
2016
    gpi->anchor_y = exit_y;
 
2017
  }
 
2018
  if ( error )
 
2019
    return error;
 
2020
 
 
2021
  (buffer->in_pos)++;
 
2022
 
 
2023
  return FT_Err_Ok;
 
2024
}
 
2025
 
 
2026
 
 
2027
/* LookupType 4 */
 
2028
 
 
2029
/* BaseArray */
 
2030
 
 
2031
static FT_Error  Load_BaseArray( HB_BaseArray*  ba,
 
2032
                                 FT_UShort       num_classes,
 
2033
                                 FT_Stream       stream )
 
2034
{
 
2035
  FT_Error  error;
 
2036
  FT_Memory memory = stream->memory;
 
2037
 
 
2038
  FT_UShort        m, n, k, count;
 
2039
  FT_ULong         cur_offset, new_offset, base_offset;
 
2040
 
 
2041
  HB_BaseRecord*  br;
 
2042
  HB_Anchor*      ban;
 
2043
 
 
2044
 
 
2045
  base_offset = FILE_Pos();
 
2046
 
 
2047
  if ( ACCESS_Frame( 2L ) )
 
2048
    return error;
 
2049
 
 
2050
  count = ba->BaseCount = GET_UShort();
 
2051
 
 
2052
  FORGET_Frame();
 
2053
 
 
2054
  ba->BaseRecord = NULL;
 
2055
 
 
2056
  if ( ALLOC_ARRAY( ba->BaseRecord, count, HB_BaseRecord ) )
 
2057
    return error;
 
2058
 
 
2059
  br = ba->BaseRecord;
 
2060
 
 
2061
  for ( m = 0; m < count; m++ )
 
2062
  {
 
2063
    br[m].BaseAnchor = NULL;
 
2064
 
 
2065
    if ( ALLOC_ARRAY( br[m].BaseAnchor, num_classes, HB_Anchor ) )
 
2066
      goto Fail;
 
2067
 
 
2068
    ban = br[m].BaseAnchor;
 
2069
 
 
2070
    for ( n = 0; n < num_classes; n++ )
 
2071
    {
 
2072
      if ( ACCESS_Frame( 2L ) )
 
2073
        goto Fail0;
 
2074
 
 
2075
      new_offset = GET_UShort() + base_offset;
 
2076
 
 
2077
      FORGET_Frame();
 
2078
 
 
2079
      if (new_offset == base_offset) {
 
2080
        /* Doulos SIL Regular is buggy and has zer offsets here.  Skip */
 
2081
        ban[n].PosFormat = 0;
 
2082
        continue;
 
2083
      }
 
2084
 
 
2085
      cur_offset = FILE_Pos();
 
2086
      if ( FILE_Seek( new_offset ) ||
 
2087
           ( error = Load_Anchor( &ban[n], stream ) ) != FT_Err_Ok )
 
2088
        goto Fail0;
 
2089
      (void)FILE_Seek( cur_offset );
 
2090
    }
 
2091
 
 
2092
    continue;
 
2093
  Fail0:
 
2094
    for ( k = 0; k < n; k++ )
 
2095
      Free_Anchor( &ban[k], memory );
 
2096
    goto Fail;
 
2097
  }
 
2098
 
 
2099
  return FT_Err_Ok;
 
2100
 
 
2101
Fail:
 
2102
  for ( k = 0; k < m; k++ )
 
2103
  {
 
2104
    ban = br[k].BaseAnchor;
 
2105
 
 
2106
    for ( n = 0; n < num_classes; n++ )
 
2107
      Free_Anchor( &ban[n], memory );
 
2108
 
 
2109
    FREE( ban );
 
2110
  }
 
2111
 
 
2112
  FREE( br );
 
2113
  return error;
 
2114
}
 
2115
 
 
2116
 
 
2117
static void  Free_BaseArray( HB_BaseArray*  ba,
 
2118
                             FT_UShort       num_classes,
 
2119
                             FT_Memory       memory )
 
2120
{
 
2121
  FT_UShort        m, n, count;
 
2122
 
 
2123
  HB_BaseRecord*  br;
 
2124
  HB_Anchor*      ban;
 
2125
 
 
2126
 
 
2127
  if ( ba->BaseRecord )
 
2128
  {
 
2129
    count = ba->BaseCount;
 
2130
    br    = ba->BaseRecord;
 
2131
 
 
2132
    for ( m = 0; m < count; m++ )
 
2133
    {
 
2134
      ban = br[m].BaseAnchor;
 
2135
 
 
2136
      for ( n = 0; n < num_classes; n++ )
 
2137
        Free_Anchor( &ban[n], memory );
 
2138
 
 
2139
      FREE( ban );
 
2140
    }
 
2141
 
 
2142
    FREE( br );
 
2143
  }
 
2144
}
 
2145
 
 
2146
 
 
2147
/* MarkBasePosFormat1 */
 
2148
 
 
2149
static FT_Error  Load_MarkBasePos( HB_GPOS_SubTable* st,
 
2150
                                   FT_Stream         stream )
 
2151
{
 
2152
  FT_Error  error;
 
2153
  FT_Memory memory = stream->memory;
 
2154
  HB_MarkBasePos* mbp = &st->markbase;
 
2155
 
 
2156
  FT_ULong  cur_offset, new_offset, base_offset;
 
2157
 
 
2158
 
 
2159
  base_offset = FILE_Pos();
 
2160
 
 
2161
  if ( ACCESS_Frame( 4L ) )
 
2162
    return error;
 
2163
 
 
2164
  mbp->PosFormat = GET_UShort();
 
2165
  new_offset     = GET_UShort() + base_offset;
 
2166
 
 
2167
  FORGET_Frame();
 
2168
 
 
2169
  if (mbp->PosFormat != 1)
 
2170
    return HB_Err_Invalid_SubTable_Format;
 
2171
 
 
2172
  cur_offset = FILE_Pos();
 
2173
  if ( FILE_Seek( new_offset ) ||
 
2174
       ( error = _HB_OPEN_Load_Coverage( &mbp->MarkCoverage, stream ) ) != FT_Err_Ok )
 
2175
    return error;
 
2176
  (void)FILE_Seek( cur_offset );
 
2177
 
 
2178
  if ( ACCESS_Frame( 2L ) )
 
2179
    goto Fail3;
 
2180
 
 
2181
  new_offset = GET_UShort() + base_offset;
 
2182
 
 
2183
  FORGET_Frame();
 
2184
 
 
2185
  cur_offset = FILE_Pos();
 
2186
  if ( FILE_Seek( new_offset ) ||
 
2187
       ( error = _HB_OPEN_Load_Coverage( &mbp->BaseCoverage, stream ) ) != FT_Err_Ok )
 
2188
    goto Fail3;
 
2189
  (void)FILE_Seek( cur_offset );
 
2190
 
 
2191
  if ( ACCESS_Frame( 4L ) )
 
2192
    goto Fail2;
 
2193
 
 
2194
  mbp->ClassCount = GET_UShort();
 
2195
  new_offset      = GET_UShort() + base_offset;
 
2196
 
 
2197
  FORGET_Frame();
 
2198
 
 
2199
  cur_offset = FILE_Pos();
 
2200
  if ( FILE_Seek( new_offset ) ||
 
2201
       ( error = Load_MarkArray( &mbp->MarkArray, stream ) ) != FT_Err_Ok )
 
2202
    goto Fail2;
 
2203
  (void)FILE_Seek( cur_offset );
 
2204
 
 
2205
  if ( ACCESS_Frame( 2L ) )
 
2206
    goto Fail1;
 
2207
 
 
2208
  new_offset = GET_UShort() + base_offset;
 
2209
 
 
2210
  FORGET_Frame();
 
2211
 
 
2212
  cur_offset = FILE_Pos();
 
2213
  if ( FILE_Seek( new_offset ) ||
 
2214
       ( error = Load_BaseArray( &mbp->BaseArray, mbp->ClassCount,
 
2215
                                 stream ) ) != FT_Err_Ok )
 
2216
    goto Fail1;
 
2217
 
 
2218
  return FT_Err_Ok;
 
2219
 
 
2220
Fail1:
 
2221
  Free_MarkArray( &mbp->MarkArray, memory );
 
2222
 
 
2223
Fail2:
 
2224
  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
 
2225
 
 
2226
Fail3:
 
2227
  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
 
2228
  return error;
 
2229
}
 
2230
 
 
2231
 
 
2232
static void  Free_MarkBasePos( HB_GPOS_SubTable* st,
 
2233
                               FT_Memory         memory )
 
2234
{
 
2235
  HB_MarkBasePos* mbp = &st->markbase;
 
2236
 
 
2237
  Free_BaseArray( &mbp->BaseArray, mbp->ClassCount, memory );
 
2238
  Free_MarkArray( &mbp->MarkArray, memory );
 
2239
  _HB_OPEN_Free_Coverage( &mbp->BaseCoverage, memory );
 
2240
  _HB_OPEN_Free_Coverage( &mbp->MarkCoverage, memory );
 
2241
}
 
2242
 
 
2243
 
 
2244
static FT_Error  Lookup_MarkBasePos( GPOS_Instance*    gpi,
 
2245
                                     HB_GPOS_SubTable* st,
 
2246
                                     HB_Buffer        buffer,
 
2247
                                     FT_UShort         flags,
 
2248
                                     FT_UShort         context_length,
 
2249
                                     int               nesting_level )
 
2250
{
 
2251
  FT_UShort        i, j, mark_index, base_index, property, class;
 
2252
  FT_Pos           x_mark_value, y_mark_value, x_base_value, y_base_value;
 
2253
  FT_Error         error;
 
2254
  HB_GPOSHeader*  gpos = gpi->gpos;
 
2255
  HB_MarkBasePos* mbp = &st->markbase;
 
2256
 
 
2257
  HB_MarkArray*   ma;
 
2258
  HB_BaseArray*   ba;
 
2259
  HB_BaseRecord*  br;
 
2260
  HB_Anchor*      mark_anchor;
 
2261
  HB_Anchor*      base_anchor;
 
2262
 
 
2263
  HB_Position     o;
 
2264
 
 
2265
  FT_UNUSED(nesting_level);
 
2266
 
 
2267
  if ( context_length != 0xFFFF && context_length < 1 )
 
2268
    return HB_Err_Not_Covered;
 
2269
 
 
2270
  if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
 
2271
    return HB_Err_Not_Covered;
 
2272
 
 
2273
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
 
2274
                       flags, &property ) )
 
2275
    return error;
 
2276
 
 
2277
  error = _HB_OPEN_Coverage_Index( &mbp->MarkCoverage, IN_CURGLYPH(),
 
2278
                          &mark_index );
 
2279
  if ( error )
 
2280
    return error;
 
2281
 
 
2282
  /* now we search backwards for a non-mark glyph */
 
2283
 
 
2284
  i = 1;
 
2285
  j = buffer->in_pos - 1;
 
2286
 
 
2287
  while ( i <= buffer->in_pos )
 
2288
  {
 
2289
    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
 
2290
                                        &property );
 
2291
    if ( error )
 
2292
      return error;
 
2293
 
 
2294
    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
 
2295
      break;
 
2296
 
 
2297
    i++;
 
2298
    j--;
 
2299
  }
 
2300
 
 
2301
  /* The following assertion is too strong -- at least for mangal.ttf. */
 
2302
#if 0
 
2303
  if ( property != HB_GDEF_BASE_GLYPH )
 
2304
    return HB_Err_Not_Covered;
 
2305
#endif
 
2306
 
 
2307
  if ( i > buffer->in_pos )
 
2308
    return HB_Err_Not_Covered;
 
2309
 
 
2310
  error = _HB_OPEN_Coverage_Index( &mbp->BaseCoverage, IN_GLYPH( j ),
 
2311
                          &base_index );
 
2312
  if ( error )
 
2313
    return error;
 
2314
 
 
2315
  ma = &mbp->MarkArray;
 
2316
 
 
2317
  if ( mark_index >= ma->MarkCount )
 
2318
    return HB_Err_Invalid_GPOS_SubTable;
 
2319
 
 
2320
  class       = ma->MarkRecord[mark_index].Class;
 
2321
  mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
 
2322
 
 
2323
  if ( class >= mbp->ClassCount )
 
2324
    return HB_Err_Invalid_GPOS_SubTable;
 
2325
 
 
2326
  ba = &mbp->BaseArray;
 
2327
 
 
2328
  if ( base_index >= ba->BaseCount )
 
2329
    return HB_Err_Invalid_GPOS_SubTable;
 
2330
 
 
2331
  br          = &ba->BaseRecord[base_index];
 
2332
  base_anchor = &br->BaseAnchor[class];
 
2333
 
 
2334
  error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
 
2335
                      &x_mark_value, &y_mark_value );
 
2336
  if ( error )
 
2337
    return error;
 
2338
 
 
2339
  error = Get_Anchor( gpi, base_anchor, IN_GLYPH( j ),
 
2340
                      &x_base_value, &y_base_value );
 
2341
  if ( error )
 
2342
    return error;
 
2343
 
 
2344
  /* anchor points are not cumulative */
 
2345
 
 
2346
  o = POSITION( buffer->in_pos );
 
2347
 
 
2348
  o->x_pos     = x_base_value - x_mark_value;
 
2349
  o->y_pos     = y_base_value - y_mark_value;
 
2350
  o->x_advance = 0;
 
2351
  o->y_advance = 0;
 
2352
  o->back      = i;
 
2353
 
 
2354
  (buffer->in_pos)++;
 
2355
 
 
2356
  return FT_Err_Ok;
 
2357
}
 
2358
 
 
2359
 
 
2360
/* LookupType 5 */
 
2361
 
 
2362
/* LigatureAttach */
 
2363
 
 
2364
static FT_Error  Load_LigatureAttach( HB_LigatureAttach*  lat,
 
2365
                                      FT_UShort            num_classes,
 
2366
                                      FT_Stream            stream )
 
2367
{
 
2368
  FT_Error  error;
 
2369
  FT_Memory memory = stream->memory;
 
2370
 
 
2371
  FT_UShort             m, n, k, count;
 
2372
  FT_ULong              cur_offset, new_offset, base_offset;
 
2373
 
 
2374
  HB_ComponentRecord*  cr;
 
2375
  HB_Anchor*           lan;
 
2376
 
 
2377
 
 
2378
  base_offset = FILE_Pos();
 
2379
 
 
2380
  if ( ACCESS_Frame( 2L ) )
 
2381
    return error;
 
2382
 
 
2383
  count = lat->ComponentCount = GET_UShort();
 
2384
 
 
2385
  FORGET_Frame();
 
2386
 
 
2387
  lat->ComponentRecord = NULL;
 
2388
 
 
2389
  if ( ALLOC_ARRAY( lat->ComponentRecord, count, HB_ComponentRecord ) )
 
2390
    return error;
 
2391
 
 
2392
  cr = lat->ComponentRecord;
 
2393
 
 
2394
  for ( m = 0; m < count; m++ )
 
2395
  {
 
2396
    cr[m].LigatureAnchor = NULL;
 
2397
 
 
2398
    if ( ALLOC_ARRAY( cr[m].LigatureAnchor, num_classes, HB_Anchor ) )
 
2399
      goto Fail;
 
2400
 
 
2401
    lan = cr[m].LigatureAnchor;
 
2402
 
 
2403
    for ( n = 0; n < num_classes; n++ )
 
2404
    {
 
2405
      if ( ACCESS_Frame( 2L ) )
 
2406
        goto Fail0;
 
2407
 
 
2408
      new_offset = GET_UShort();
 
2409
 
 
2410
      FORGET_Frame();
 
2411
 
 
2412
      if ( new_offset )
 
2413
      {
 
2414
        new_offset += base_offset;
 
2415
 
 
2416
        cur_offset = FILE_Pos();
 
2417
        if ( FILE_Seek( new_offset ) ||
 
2418
             ( error = Load_Anchor( &lan[n], stream ) ) != FT_Err_Ok )
 
2419
          goto Fail0;
 
2420
        (void)FILE_Seek( cur_offset );
 
2421
      }
 
2422
      else
 
2423
        lan[n].PosFormat = 0;
 
2424
    }
 
2425
 
 
2426
    continue;
 
2427
  Fail0:
 
2428
    for ( k = 0; k < n; k++ )
 
2429
      Free_Anchor( &lan[k], memory );
 
2430
    goto Fail;
 
2431
  }
 
2432
 
 
2433
  return FT_Err_Ok;
 
2434
 
 
2435
Fail:
 
2436
  for ( k = 0; k < m; k++ )
 
2437
  {
 
2438
    lan = cr[k].LigatureAnchor;
 
2439
 
 
2440
    for ( n = 0; n < num_classes; n++ )
 
2441
      Free_Anchor( &lan[n], memory );
 
2442
 
 
2443
    FREE( lan );
 
2444
  }
 
2445
 
 
2446
  FREE( cr );
 
2447
  return error;
 
2448
}
 
2449
 
 
2450
 
 
2451
static void  Free_LigatureAttach( HB_LigatureAttach*  lat,
 
2452
                                  FT_UShort            num_classes,
 
2453
                                  FT_Memory            memory )
 
2454
{
 
2455
  FT_UShort        m, n, count;
 
2456
 
 
2457
  HB_ComponentRecord*  cr;
 
2458
  HB_Anchor*           lan;
 
2459
 
 
2460
 
 
2461
  if ( lat->ComponentRecord )
 
2462
  {
 
2463
    count = lat->ComponentCount;
 
2464
    cr    = lat->ComponentRecord;
 
2465
 
 
2466
    for ( m = 0; m < count; m++ )
 
2467
    {
 
2468
      lan = cr[m].LigatureAnchor;
 
2469
 
 
2470
      for ( n = 0; n < num_classes; n++ )
 
2471
        Free_Anchor( &lan[n], memory );
 
2472
 
 
2473
      FREE( lan );
 
2474
    }
 
2475
 
 
2476
    FREE( cr );
 
2477
  }
 
2478
}
 
2479
 
 
2480
 
 
2481
/* LigatureArray */
 
2482
 
 
2483
static FT_Error  Load_LigatureArray( HB_LigatureArray*  la,
 
2484
                                     FT_UShort           num_classes,
 
2485
                                     FT_Stream           stream )
 
2486
{
 
2487
  FT_Error  error;
 
2488
  FT_Memory memory = stream->memory;
 
2489
 
 
2490
  FT_UShort            n, m, count;
 
2491
  FT_ULong             cur_offset, new_offset, base_offset;
 
2492
 
 
2493
  HB_LigatureAttach*  lat;
 
2494
 
 
2495
 
 
2496
  base_offset = FILE_Pos();
 
2497
 
 
2498
  if ( ACCESS_Frame( 2L ) )
 
2499
    return error;
 
2500
 
 
2501
  count = la->LigatureCount = GET_UShort();
 
2502
 
 
2503
  FORGET_Frame();
 
2504
 
 
2505
  la->LigatureAttach = NULL;
 
2506
 
 
2507
  if ( ALLOC_ARRAY( la->LigatureAttach, count, HB_LigatureAttach ) )
 
2508
    return error;
 
2509
 
 
2510
  lat = la->LigatureAttach;
 
2511
 
 
2512
  for ( n = 0; n < count; n++ )
 
2513
  {
 
2514
    if ( ACCESS_Frame( 2L ) )
 
2515
      goto Fail;
 
2516
 
 
2517
    new_offset = GET_UShort() + base_offset;
 
2518
 
 
2519
    FORGET_Frame();
 
2520
 
 
2521
    cur_offset = FILE_Pos();
 
2522
    if ( FILE_Seek( new_offset ) ||
 
2523
         ( error = Load_LigatureAttach( &lat[n], num_classes,
 
2524
                                        stream ) ) != FT_Err_Ok )
 
2525
      goto Fail;
 
2526
    (void)FILE_Seek( cur_offset );
 
2527
  }
 
2528
 
 
2529
  return FT_Err_Ok;
 
2530
 
 
2531
Fail:
 
2532
  for ( m = 0; m < n; m++ )
 
2533
    Free_LigatureAttach( &lat[m], num_classes, memory );
 
2534
 
 
2535
  FREE( lat );
 
2536
  return error;
 
2537
}
 
2538
 
 
2539
 
 
2540
static void  Free_LigatureArray( HB_LigatureArray*  la,
 
2541
                                 FT_UShort           num_classes,
 
2542
                                 FT_Memory           memory )
 
2543
{
 
2544
  FT_UShort            n, count;
 
2545
 
 
2546
  HB_LigatureAttach*  lat;
 
2547
 
 
2548
 
 
2549
  if ( la->LigatureAttach )
 
2550
  {
 
2551
    count = la->LigatureCount;
 
2552
    lat   = la->LigatureAttach;
 
2553
 
 
2554
    for ( n = 0; n < count; n++ )
 
2555
      Free_LigatureAttach( &lat[n], num_classes, memory );
 
2556
 
 
2557
    FREE( lat );
 
2558
  }
 
2559
}
 
2560
 
 
2561
 
 
2562
/* MarkLigPosFormat1 */
 
2563
 
 
2564
static FT_Error  Load_MarkLigPos( HB_GPOS_SubTable* st,
 
2565
                                  FT_Stream        stream )
 
2566
{
 
2567
  FT_Error  error;
 
2568
  FT_Memory memory = stream->memory;
 
2569
  HB_MarkLigPos*  mlp = &st->marklig;
 
2570
 
 
2571
  FT_ULong  cur_offset, new_offset, base_offset;
 
2572
 
 
2573
 
 
2574
  base_offset = FILE_Pos();
 
2575
 
 
2576
  if ( ACCESS_Frame( 4L ) )
 
2577
    return error;
 
2578
 
 
2579
  mlp->PosFormat = GET_UShort();
 
2580
  new_offset     = GET_UShort() + base_offset;
 
2581
 
 
2582
  FORGET_Frame();
 
2583
 
 
2584
  cur_offset = FILE_Pos();
 
2585
  if ( FILE_Seek( new_offset ) ||
 
2586
       ( error = _HB_OPEN_Load_Coverage( &mlp->MarkCoverage, stream ) ) != FT_Err_Ok )
 
2587
    return error;
 
2588
  (void)FILE_Seek( cur_offset );
 
2589
 
 
2590
  if ( ACCESS_Frame( 2L ) )
 
2591
    goto Fail3;
 
2592
 
 
2593
  new_offset = GET_UShort() + base_offset;
 
2594
 
 
2595
  FORGET_Frame();
 
2596
 
 
2597
  cur_offset = FILE_Pos();
 
2598
  if ( FILE_Seek( new_offset ) ||
 
2599
       ( error = _HB_OPEN_Load_Coverage( &mlp->LigatureCoverage,
 
2600
                                stream ) ) != FT_Err_Ok )
 
2601
    goto Fail3;
 
2602
  (void)FILE_Seek( cur_offset );
 
2603
 
 
2604
  if ( ACCESS_Frame( 4L ) )
 
2605
    goto Fail2;
 
2606
 
 
2607
  mlp->ClassCount = GET_UShort();
 
2608
  new_offset      = GET_UShort() + base_offset;
 
2609
 
 
2610
  FORGET_Frame();
 
2611
 
 
2612
  cur_offset = FILE_Pos();
 
2613
  if ( FILE_Seek( new_offset ) ||
 
2614
       ( error = Load_MarkArray( &mlp->MarkArray, stream ) ) != FT_Err_Ok )
 
2615
    goto Fail2;
 
2616
  (void)FILE_Seek( cur_offset );
 
2617
 
 
2618
  if ( ACCESS_Frame( 2L ) )
 
2619
    goto Fail1;
 
2620
 
 
2621
  new_offset = GET_UShort() + base_offset;
 
2622
 
 
2623
  FORGET_Frame();
 
2624
 
 
2625
  cur_offset = FILE_Pos();
 
2626
  if ( FILE_Seek( new_offset ) ||
 
2627
       ( error = Load_LigatureArray( &mlp->LigatureArray, mlp->ClassCount,
 
2628
                                     stream ) ) != FT_Err_Ok )
 
2629
    goto Fail1;
 
2630
 
 
2631
  return FT_Err_Ok;
 
2632
 
 
2633
Fail1:
 
2634
  Free_MarkArray( &mlp->MarkArray, memory );
 
2635
 
 
2636
Fail2:
 
2637
  _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
 
2638
 
 
2639
Fail3:
 
2640
  _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
 
2641
  return error;
 
2642
}
 
2643
 
 
2644
 
 
2645
static void  Free_MarkLigPos( HB_GPOS_SubTable* st,
 
2646
                              FT_Memory        memory)
 
2647
{
 
2648
  HB_MarkLigPos*  mlp = &st->marklig;
 
2649
 
 
2650
  Free_LigatureArray( &mlp->LigatureArray, mlp->ClassCount, memory );
 
2651
  Free_MarkArray( &mlp->MarkArray, memory );
 
2652
  _HB_OPEN_Free_Coverage( &mlp->LigatureCoverage, memory );
 
2653
  _HB_OPEN_Free_Coverage( &mlp->MarkCoverage, memory );
 
2654
}
 
2655
 
 
2656
 
 
2657
static FT_Error  Lookup_MarkLigPos( GPOS_Instance*    gpi,
 
2658
                                    HB_GPOS_SubTable* st,
 
2659
                                    HB_Buffer        buffer,
 
2660
                                    FT_UShort         flags,
 
2661
                                    FT_UShort         context_length,
 
2662
                                    int               nesting_level )
 
2663
{
 
2664
  FT_UShort        i, j, mark_index, lig_index, property, class;
 
2665
  FT_UShort        mark_glyph;
 
2666
  FT_Pos           x_mark_value, y_mark_value, x_lig_value, y_lig_value;
 
2667
  FT_Error         error;
 
2668
  HB_GPOSHeader*  gpos = gpi->gpos;
 
2669
  HB_MarkLigPos*  mlp = &st->marklig;
 
2670
 
 
2671
  HB_MarkArray*        ma;
 
2672
  HB_LigatureArray*    la;
 
2673
  HB_LigatureAttach*   lat;
 
2674
  HB_ComponentRecord*  cr;
 
2675
  FT_UShort             comp_index;
 
2676
  HB_Anchor*           mark_anchor;
 
2677
  HB_Anchor*           lig_anchor;
 
2678
 
 
2679
  HB_Position    o;
 
2680
 
 
2681
  FT_UNUSED(nesting_level);
 
2682
 
 
2683
  if ( context_length != 0xFFFF && context_length < 1 )
 
2684
    return HB_Err_Not_Covered;
 
2685
 
 
2686
  if ( flags & HB_LOOKUP_FLAG_IGNORE_LIGATURES )
 
2687
    return HB_Err_Not_Covered;
 
2688
 
 
2689
  mark_glyph = IN_CURGLYPH();
 
2690
 
 
2691
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
 
2692
    return error;
 
2693
 
 
2694
  error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
 
2695
  if ( error )
 
2696
    return error;
 
2697
 
 
2698
  /* now we search backwards for a non-mark glyph */
 
2699
 
 
2700
  i = 1;
 
2701
  j = buffer->in_pos - 1;
 
2702
 
 
2703
  while ( i <= buffer->in_pos )
 
2704
  {
 
2705
    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
 
2706
                                        &property );
 
2707
    if ( error )
 
2708
      return error;
 
2709
 
 
2710
    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
 
2711
      break;
 
2712
 
 
2713
    i++;
 
2714
    j--;
 
2715
  }
 
2716
 
 
2717
  /* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
 
2718
     too strong, thus it is commented out.                             */
 
2719
#if 0
 
2720
  if ( property != HB_GDEF_LIGATURE )
 
2721
    return HB_Err_Not_Covered;
 
2722
#endif
 
2723
 
 
2724
  if ( i > buffer->in_pos )
 
2725
    return HB_Err_Not_Covered;
 
2726
 
 
2727
  error = _HB_OPEN_Coverage_Index( &mlp->LigatureCoverage, IN_GLYPH( j ),
 
2728
                          &lig_index );
 
2729
  if ( error )
 
2730
    return error;
 
2731
 
 
2732
  ma = &mlp->MarkArray;
 
2733
 
 
2734
  if ( mark_index >= ma->MarkCount )
 
2735
    return HB_Err_Invalid_GPOS_SubTable;
 
2736
 
 
2737
  class       = ma->MarkRecord[mark_index].Class;
 
2738
  mark_anchor = &ma->MarkRecord[mark_index].MarkAnchor;
 
2739
 
 
2740
  if ( class >= mlp->ClassCount )
 
2741
    return HB_Err_Invalid_GPOS_SubTable;
 
2742
 
 
2743
  la = &mlp->LigatureArray;
 
2744
 
 
2745
  if ( lig_index >= la->LigatureCount )
 
2746
    return HB_Err_Invalid_GPOS_SubTable;
 
2747
 
 
2748
  lat = &la->LigatureAttach[lig_index];
 
2749
 
 
2750
  /* We must now check whether the ligature ID of the current mark glyph
 
2751
     is identical to the ligature ID of the found ligature.  If yes, we
 
2752
     can directly use the component index.  If not, we attach the mark
 
2753
     glyph to the last component of the ligature.                        */
 
2754
 
 
2755
  if ( IN_LIGID( j ) == IN_LIGID( buffer->in_pos) )
 
2756
  {
 
2757
    comp_index = IN_COMPONENT( buffer->in_pos );
 
2758
    if ( comp_index >= lat->ComponentCount )
 
2759
      return HB_Err_Not_Covered;
 
2760
  }
 
2761
  else
 
2762
    comp_index = lat->ComponentCount - 1;
 
2763
 
 
2764
  cr         = &lat->ComponentRecord[comp_index];
 
2765
  lig_anchor = &cr->LigatureAnchor[class];
 
2766
 
 
2767
  error = Get_Anchor( gpi, mark_anchor, IN_CURGLYPH(),
 
2768
                      &x_mark_value, &y_mark_value );
 
2769
  if ( error )
 
2770
    return error;
 
2771
  error = Get_Anchor( gpi, lig_anchor, IN_GLYPH( j ),
 
2772
                      &x_lig_value, &y_lig_value );
 
2773
  if ( error )
 
2774
    return error;
 
2775
 
 
2776
  /* anchor points are not cumulative */
 
2777
 
 
2778
  o = POSITION( buffer->in_pos );
 
2779
 
 
2780
  o->x_pos     = x_lig_value - x_mark_value;
 
2781
  o->y_pos     = y_lig_value - y_mark_value;
 
2782
  o->x_advance = 0;
 
2783
  o->y_advance = 0;
 
2784
  o->back      = i;
 
2785
 
 
2786
  (buffer->in_pos)++;
 
2787
 
 
2788
  return FT_Err_Ok;
 
2789
}
 
2790
 
 
2791
 
 
2792
/* LookupType 6 */
 
2793
 
 
2794
/* Mark2Array */
 
2795
 
 
2796
static FT_Error  Load_Mark2Array( HB_Mark2Array*  m2a,
 
2797
                                  FT_UShort        num_classes,
 
2798
                                  FT_Stream        stream )
 
2799
{
 
2800
  FT_Error  error;
 
2801
  FT_Memory memory = stream->memory;
 
2802
 
 
2803
  FT_UShort         k, m, n, count;
 
2804
  FT_ULong          cur_offset, new_offset, base_offset;
 
2805
 
 
2806
  HB_Mark2Record*  m2r;
 
2807
  HB_Anchor*       m2an;
 
2808
 
 
2809
 
 
2810
  base_offset = FILE_Pos();
 
2811
 
 
2812
  if ( ACCESS_Frame( 2L ) )
 
2813
    return error;
 
2814
 
 
2815
  count = m2a->Mark2Count = GET_UShort();
 
2816
 
 
2817
  FORGET_Frame();
 
2818
 
 
2819
  m2a->Mark2Record = NULL;
 
2820
 
 
2821
  if ( ALLOC_ARRAY( m2a->Mark2Record, count, HB_Mark2Record ) )
 
2822
    return error;
 
2823
 
 
2824
  m2r = m2a->Mark2Record;
 
2825
 
 
2826
  for ( m = 0; m < count; m++ )
 
2827
  {
 
2828
    m2r[m].Mark2Anchor = NULL;
 
2829
 
 
2830
    if ( ALLOC_ARRAY( m2r[m].Mark2Anchor, num_classes, HB_Anchor ) )
 
2831
      goto Fail;
 
2832
 
 
2833
    m2an = m2r[m].Mark2Anchor;
 
2834
 
 
2835
    for ( n = 0; n < num_classes; n++ )
 
2836
    {
 
2837
      if ( ACCESS_Frame( 2L ) )
 
2838
        goto Fail0;
 
2839
 
 
2840
      new_offset = GET_UShort() + base_offset;
 
2841
 
 
2842
      FORGET_Frame();
 
2843
 
 
2844
      cur_offset = FILE_Pos();
 
2845
      if ( FILE_Seek( new_offset ) ||
 
2846
           ( error = Load_Anchor( &m2an[n], stream ) ) != FT_Err_Ok )
 
2847
        goto Fail0;
 
2848
      (void)FILE_Seek( cur_offset );
 
2849
    }
 
2850
 
 
2851
    continue;
 
2852
  Fail0:
 
2853
    for ( k = 0; k < n; k++ )
 
2854
      Free_Anchor( &m2an[k], memory );
 
2855
    goto Fail;
 
2856
  }
 
2857
 
 
2858
  return FT_Err_Ok;
 
2859
 
 
2860
Fail:
 
2861
  for ( k = 0; k < m; k++ )
 
2862
  {
 
2863
    m2an = m2r[k].Mark2Anchor;
 
2864
 
 
2865
    for ( n = 0; n < num_classes; n++ )
 
2866
      Free_Anchor( &m2an[n], memory );
 
2867
 
 
2868
    FREE( m2an );
 
2869
  }
 
2870
 
 
2871
  FREE( m2r );
 
2872
  return error;
 
2873
}
 
2874
 
 
2875
 
 
2876
static void  Free_Mark2Array( HB_Mark2Array*  m2a,
 
2877
                              FT_UShort        num_classes,
 
2878
                              FT_Memory        memory )
 
2879
{
 
2880
  FT_UShort         m, n, count;
 
2881
 
 
2882
  HB_Mark2Record*  m2r;
 
2883
  HB_Anchor*       m2an;
 
2884
 
 
2885
 
 
2886
  if ( m2a->Mark2Record )
 
2887
  {
 
2888
    count = m2a->Mark2Count;
 
2889
    m2r   = m2a->Mark2Record;
 
2890
 
 
2891
    for ( m = 0; m < count; m++ )
 
2892
    {
 
2893
      m2an = m2r[m].Mark2Anchor;
 
2894
 
 
2895
      for ( n = 0; n < num_classes; n++ )
 
2896
        Free_Anchor( &m2an[n], memory );
 
2897
 
 
2898
      FREE( m2an );
 
2899
    }
 
2900
 
 
2901
    FREE( m2r );
 
2902
  }
 
2903
}
 
2904
 
 
2905
 
 
2906
/* MarkMarkPosFormat1 */
 
2907
 
 
2908
static FT_Error  Load_MarkMarkPos( HB_GPOS_SubTable* st,
 
2909
                                   FT_Stream         stream )
 
2910
{
 
2911
  FT_Error  error;
 
2912
  FT_Memory memory = stream->memory;
 
2913
  HB_MarkMarkPos* mmp = &st->markmark;
 
2914
 
 
2915
  FT_ULong  cur_offset, new_offset, base_offset;
 
2916
 
 
2917
 
 
2918
  base_offset = FILE_Pos();
 
2919
 
 
2920
  if ( ACCESS_Frame( 4L ) )
 
2921
    return error;
 
2922
 
 
2923
  mmp->PosFormat = GET_UShort();
 
2924
  new_offset     = GET_UShort() + base_offset;
 
2925
 
 
2926
  FORGET_Frame();
 
2927
 
 
2928
  cur_offset = FILE_Pos();
 
2929
  if ( FILE_Seek( new_offset ) ||
 
2930
       ( error = _HB_OPEN_Load_Coverage( &mmp->Mark1Coverage,
 
2931
                                stream ) ) != FT_Err_Ok )
 
2932
    return error;
 
2933
  (void)FILE_Seek( cur_offset );
 
2934
 
 
2935
  if ( ACCESS_Frame( 2L ) )
 
2936
    goto Fail3;
 
2937
 
 
2938
  new_offset = GET_UShort() + base_offset;
 
2939
 
 
2940
  FORGET_Frame();
 
2941
 
 
2942
  cur_offset = FILE_Pos();
 
2943
  if ( FILE_Seek( new_offset ) ||
 
2944
       ( error = _HB_OPEN_Load_Coverage( &mmp->Mark2Coverage,
 
2945
                                stream ) ) != FT_Err_Ok )
 
2946
    goto Fail3;
 
2947
  (void)FILE_Seek( cur_offset );
 
2948
 
 
2949
  if ( ACCESS_Frame( 4L ) )
 
2950
    goto Fail2;
 
2951
 
 
2952
  mmp->ClassCount = GET_UShort();
 
2953
  new_offset      = GET_UShort() + base_offset;
 
2954
 
 
2955
  FORGET_Frame();
 
2956
 
 
2957
  cur_offset = FILE_Pos();
 
2958
  if ( FILE_Seek( new_offset ) ||
 
2959
       ( error = Load_MarkArray( &mmp->Mark1Array, stream ) ) != FT_Err_Ok )
 
2960
    goto Fail2;
 
2961
  (void)FILE_Seek( cur_offset );
 
2962
 
 
2963
  if ( ACCESS_Frame( 2L ) )
 
2964
    goto Fail1;
 
2965
 
 
2966
  new_offset = GET_UShort() + base_offset;
 
2967
 
 
2968
  FORGET_Frame();
 
2969
 
 
2970
  cur_offset = FILE_Pos();
 
2971
  if ( FILE_Seek( new_offset ) ||
 
2972
       ( error = Load_Mark2Array( &mmp->Mark2Array, mmp->ClassCount,
 
2973
                                  stream ) ) != FT_Err_Ok )
 
2974
    goto Fail1;
 
2975
 
 
2976
  return FT_Err_Ok;
 
2977
 
 
2978
Fail1:
 
2979
  Free_MarkArray( &mmp->Mark1Array, memory );
 
2980
 
 
2981
Fail2:
 
2982
  _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
 
2983
 
 
2984
Fail3:
 
2985
  _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
 
2986
  return error;
 
2987
}
 
2988
 
 
2989
 
 
2990
static void  Free_MarkMarkPos( HB_GPOS_SubTable* st,
 
2991
                               FT_Memory         memory)
 
2992
{
 
2993
  HB_MarkMarkPos* mmp = &st->markmark;
 
2994
 
 
2995
  Free_Mark2Array( &mmp->Mark2Array, mmp->ClassCount, memory );
 
2996
  Free_MarkArray( &mmp->Mark1Array, memory );
 
2997
  _HB_OPEN_Free_Coverage( &mmp->Mark2Coverage, memory );
 
2998
  _HB_OPEN_Free_Coverage( &mmp->Mark1Coverage, memory );
 
2999
}
 
3000
 
 
3001
 
 
3002
static FT_Error  Lookup_MarkMarkPos( GPOS_Instance*    gpi,
 
3003
                                     HB_GPOS_SubTable* st,
 
3004
                                     HB_Buffer        buffer,
 
3005
                                     FT_UShort         flags,
 
3006
                                     FT_UShort         context_length,
 
3007
                                     int               nesting_level )
 
3008
{
 
3009
  FT_UShort        i, j, mark1_index, mark2_index, property, class;
 
3010
  FT_Pos           x_mark1_value, y_mark1_value,
 
3011
                   x_mark2_value, y_mark2_value;
 
3012
  FT_Error         error;
 
3013
  HB_GPOSHeader*  gpos = gpi->gpos;
 
3014
  HB_MarkMarkPos* mmp = &st->markmark;
 
3015
 
 
3016
  HB_MarkArray*    ma1;
 
3017
  HB_Mark2Array*   ma2;
 
3018
  HB_Mark2Record*  m2r;
 
3019
  HB_Anchor*       mark1_anchor;
 
3020
  HB_Anchor*       mark2_anchor;
 
3021
 
 
3022
  HB_Position    o;
 
3023
 
 
3024
  FT_UNUSED(nesting_level);
 
3025
 
 
3026
  if ( context_length != 0xFFFF && context_length < 1 )
 
3027
    return HB_Err_Not_Covered;
 
3028
 
 
3029
  if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
 
3030
    return HB_Err_Not_Covered;
 
3031
 
 
3032
  if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
 
3033
                       flags, &property ) )
 
3034
    return error;
 
3035
 
 
3036
  error = _HB_OPEN_Coverage_Index( &mmp->Mark1Coverage, IN_CURGLYPH(),
 
3037
                          &mark1_index );
 
3038
  if ( error )
 
3039
    return error;
 
3040
 
 
3041
  /* now we search backwards for a suitable mark glyph until a non-mark
 
3042
     glyph                                                */
 
3043
 
 
3044
  if ( buffer->in_pos == 0 )
 
3045
    return HB_Err_Not_Covered;
 
3046
 
 
3047
  i = 1;
 
3048
  j = buffer->in_pos - 1;
 
3049
  while ( i <= buffer->in_pos )
 
3050
  {
 
3051
    error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
 
3052
                                        &property );
 
3053
    if ( error )
 
3054
      return error;
 
3055
 
 
3056
    if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
 
3057
      return HB_Err_Not_Covered;
 
3058
 
 
3059
    if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
 
3060
    {
 
3061
      if ( property == (flags & 0xFF00) )
 
3062
        break;
 
3063
    }
 
3064
    else
 
3065
      break;
 
3066
 
 
3067
    i++;
 
3068
    j--;
 
3069
  }
 
3070
 
 
3071
  error = _HB_OPEN_Coverage_Index( &mmp->Mark2Coverage, IN_GLYPH( j ),
 
3072
                          &mark2_index );
 
3073
  if ( error )
 
3074
    return error;
 
3075
 
 
3076
  ma1 = &mmp->Mark1Array;
 
3077
 
 
3078
  if ( mark1_index >= ma1->MarkCount )
 
3079
    return HB_Err_Invalid_GPOS_SubTable;
 
3080
 
 
3081
  class        = ma1->MarkRecord[mark1_index].Class;
 
3082
  mark1_anchor = &ma1->MarkRecord[mark1_index].MarkAnchor;
 
3083
 
 
3084
  if ( class >= mmp->ClassCount )
 
3085
    return HB_Err_Invalid_GPOS_SubTable;
 
3086
 
 
3087
  ma2 = &mmp->Mark2Array;
 
3088
 
 
3089
  if ( mark2_index >= ma2->Mark2Count )
 
3090
    return HB_Err_Invalid_GPOS_SubTable;
 
3091
 
 
3092
  m2r          = &ma2->Mark2Record[mark2_index];
 
3093
  mark2_anchor = &m2r->Mark2Anchor[class];
 
3094
 
 
3095
  error = Get_Anchor( gpi, mark1_anchor, IN_CURGLYPH(),
 
3096
                      &x_mark1_value, &y_mark1_value );
 
3097
  if ( error )
 
3098
    return error;
 
3099
  error = Get_Anchor( gpi, mark2_anchor, IN_GLYPH( j ),
 
3100
                      &x_mark2_value, &y_mark2_value );
 
3101
  if ( error )
 
3102
    return error;
 
3103
 
 
3104
  /* anchor points are not cumulative */
 
3105
 
 
3106
  o = POSITION( buffer->in_pos );
 
3107
 
 
3108
  o->x_pos     = x_mark2_value - x_mark1_value;
 
3109
  o->y_pos     = y_mark2_value - y_mark1_value;
 
3110
  o->x_advance = 0;
 
3111
  o->y_advance = 0;
 
3112
  o->back      = 1;
 
3113
 
 
3114
  (buffer->in_pos)++;
 
3115
 
 
3116
  return FT_Err_Ok;
 
3117
}
 
3118
 
 
3119
 
 
3120
/* Do the actual positioning for a context positioning (either format
 
3121
   7 or 8).  This is only called after we've determined that the stream
 
3122
   matches the subrule.                                                 */
 
3123
 
 
3124
static FT_Error  Do_ContextPos( GPOS_Instance*        gpi,
 
3125
                                FT_UShort             GlyphCount,
 
3126
                                FT_UShort             PosCount,
 
3127
                                HB_PosLookupRecord*  pos,
 
3128
                                HB_Buffer            buffer,
 
3129
                                int                   nesting_level )
 
3130
{
 
3131
  FT_Error  error;
 
3132
  FT_UShort i, old_pos;
 
3133
 
 
3134
 
 
3135
  i = 0;
 
3136
 
 
3137
  while ( i < GlyphCount )
 
3138
  {
 
3139
    if ( PosCount && i == pos->SequenceIndex )
 
3140
    {
 
3141
      old_pos = buffer->in_pos;
 
3142
 
 
3143
      /* Do a positioning */
 
3144
 
 
3145
      error = GPOS_Do_Glyph_Lookup( gpi, pos->LookupListIndex, buffer,
 
3146
                                    GlyphCount, nesting_level );
 
3147
 
 
3148
      if ( error )
 
3149
        return error;
 
3150
 
 
3151
      pos++;
 
3152
      PosCount--;
 
3153
      i += buffer->in_pos - old_pos;
 
3154
    }
 
3155
    else
 
3156
    {
 
3157
      i++;
 
3158
      (buffer->in_pos)++;
 
3159
    }
 
3160
  }
 
3161
 
 
3162
  return FT_Err_Ok;
 
3163
}
 
3164
 
 
3165
 
 
3166
/* LookupType 7 */
 
3167
 
 
3168
/* PosRule */
 
3169
 
 
3170
static FT_Error  Load_PosRule( HB_PosRule*  pr,
 
3171
                               FT_Stream     stream )
 
3172
{
 
3173
  FT_Error  error;
 
3174
  FT_Memory memory = stream->memory;
 
3175
 
 
3176
  FT_UShort             n, count;
 
3177
  FT_UShort*            i;
 
3178
 
 
3179
  HB_PosLookupRecord*  plr;
 
3180
 
 
3181
 
 
3182
  if ( ACCESS_Frame( 4L ) )
 
3183
    return error;
 
3184
 
 
3185
  pr->GlyphCount = GET_UShort();
 
3186
  pr->PosCount   = GET_UShort();
 
3187
 
 
3188
  FORGET_Frame();
 
3189
 
 
3190
  pr->Input = NULL;
 
3191
 
 
3192
  count = pr->GlyphCount - 1;         /* only GlyphCount - 1 elements */
 
3193
 
 
3194
  if ( ALLOC_ARRAY( pr->Input, count, FT_UShort ) )
 
3195
    return error;
 
3196
 
 
3197
  i = pr->Input;
 
3198
 
 
3199
  if ( ACCESS_Frame( count * 2L ) )
 
3200
    goto Fail2;
 
3201
 
 
3202
  for ( n = 0; n < count; n++ )
 
3203
    i[n] = GET_UShort();
 
3204
 
 
3205
  FORGET_Frame();
 
3206
 
 
3207
  pr->PosLookupRecord = NULL;
 
3208
 
 
3209
  count = pr->PosCount;
 
3210
 
 
3211
  if ( ALLOC_ARRAY( pr->PosLookupRecord, count, HB_PosLookupRecord ) )
 
3212
    goto Fail2;
 
3213
 
 
3214
  plr = pr->PosLookupRecord;
 
3215
 
 
3216
  if ( ACCESS_Frame( count * 4L ) )
 
3217
    goto Fail1;
 
3218
 
 
3219
  for ( n = 0; n < count; n++ )
 
3220
  {
 
3221
    plr[n].SequenceIndex   = GET_UShort();
 
3222
    plr[n].LookupListIndex = GET_UShort();
 
3223
  }
 
3224
 
 
3225
  FORGET_Frame();
 
3226
 
 
3227
  return FT_Err_Ok;
 
3228
 
 
3229
Fail1:
 
3230
  FREE( plr );
 
3231
 
 
3232
Fail2:
 
3233
  FREE( i );
 
3234
  return error;
 
3235
}
 
3236
 
 
3237
 
 
3238
static void  Free_PosRule( HB_PosRule*  pr,
 
3239
                           FT_Memory     memory )
 
3240
{
 
3241
  FREE( pr->PosLookupRecord );
 
3242
  FREE( pr->Input );
 
3243
}
 
3244
 
 
3245
 
 
3246
/* PosRuleSet */
 
3247
 
 
3248
static FT_Error  Load_PosRuleSet( HB_PosRuleSet*  prs,
 
3249
                                  FT_Stream        stream )
 
3250
{
 
3251
  FT_Error  error;
 
3252
  FT_Memory memory = stream->memory;
 
3253
 
 
3254
  FT_UShort     n, m, count;
 
3255
  FT_ULong      cur_offset, new_offset, base_offset;
 
3256
 
 
3257
  HB_PosRule*  pr;
 
3258
 
 
3259
 
 
3260
  base_offset = FILE_Pos();
 
3261
 
 
3262
  if ( ACCESS_Frame( 2L ) )
 
3263
    return error;
 
3264
 
 
3265
  count = prs->PosRuleCount = GET_UShort();
 
3266
 
 
3267
  FORGET_Frame();
 
3268
 
 
3269
  prs->PosRule = NULL;
 
3270
 
 
3271
  if ( ALLOC_ARRAY( prs->PosRule, count, HB_PosRule ) )
 
3272
    return error;
 
3273
 
 
3274
  pr = prs->PosRule;
 
3275
 
 
3276
  for ( n = 0; n < count; n++ )
 
3277
  {
 
3278
    if ( ACCESS_Frame( 2L ) )
 
3279
      goto Fail;
 
3280
 
 
3281
    new_offset = GET_UShort() + base_offset;
 
3282
 
 
3283
    FORGET_Frame();
 
3284
 
 
3285
    cur_offset = FILE_Pos();
 
3286
    if ( FILE_Seek( new_offset ) ||
 
3287
         ( error = Load_PosRule( &pr[n], stream ) ) != FT_Err_Ok )
 
3288
      goto Fail;
 
3289
    (void)FILE_Seek( cur_offset );
 
3290
  }
 
3291
 
 
3292
  return FT_Err_Ok;
 
3293
 
 
3294
Fail:
 
3295
  for ( m = 0; m < n; m++ )
 
3296
    Free_PosRule( &pr[m], memory );
 
3297
 
 
3298
  FREE( pr );
 
3299
  return error;
 
3300
}
 
3301
 
 
3302
 
 
3303
static void  Free_PosRuleSet( HB_PosRuleSet*  prs,
 
3304
                              FT_Memory        memory )
 
3305
{
 
3306
  FT_UShort     n, count;
 
3307
 
 
3308
  HB_PosRule*  pr;
 
3309
 
 
3310
 
 
3311
  if ( prs->PosRule )
 
3312
  {
 
3313
    count = prs->PosRuleCount;
 
3314
    pr    = prs->PosRule;
 
3315
 
 
3316
    for ( n = 0; n < count; n++ )
 
3317
      Free_PosRule( &pr[n], memory );
 
3318
 
 
3319
    FREE( pr );
 
3320
  }
 
3321
}
 
3322
 
 
3323
 
 
3324
/* ContextPosFormat1 */
 
3325
 
 
3326
static FT_Error  Load_ContextPos1( HB_ContextPosFormat1*  cpf1,
 
3327
                                   FT_Stream               stream )
 
3328
{
 
3329
  FT_Error  error;
 
3330
  FT_Memory memory = stream->memory;
 
3331
 
 
3332
  FT_UShort        n, m, count;
 
3333
  FT_ULong         cur_offset, new_offset, base_offset;
 
3334
 
 
3335
  HB_PosRuleSet*  prs;
 
3336
 
 
3337
 
 
3338
  base_offset = FILE_Pos() - 2L;
 
3339
 
 
3340
  if ( ACCESS_Frame( 2L ) )
 
3341
    return error;
 
3342
 
 
3343
  new_offset = GET_UShort() + base_offset;
 
3344
 
 
3345
  FORGET_Frame();
 
3346
 
 
3347
  cur_offset = FILE_Pos();
 
3348
  if ( FILE_Seek( new_offset ) ||
 
3349
       ( error = _HB_OPEN_Load_Coverage( &cpf1->Coverage, stream ) ) != FT_Err_Ok )
 
3350
    return error;
 
3351
  (void)FILE_Seek( cur_offset );
 
3352
 
 
3353
  if ( ACCESS_Frame( 2L ) )
 
3354
    goto Fail2;
 
3355
 
 
3356
  count = cpf1->PosRuleSetCount = GET_UShort();
 
3357
 
 
3358
  FORGET_Frame();
 
3359
 
 
3360
  cpf1->PosRuleSet = NULL;
 
3361
 
 
3362
  if ( ALLOC_ARRAY( cpf1->PosRuleSet, count, HB_PosRuleSet ) )
 
3363
    goto Fail2;
 
3364
 
 
3365
  prs = cpf1->PosRuleSet;
 
3366
 
 
3367
  for ( n = 0; n < count; n++ )
 
3368
  {
 
3369
    if ( ACCESS_Frame( 2L ) )
 
3370
      goto Fail1;
 
3371
 
 
3372
    new_offset = GET_UShort() + base_offset;
 
3373
 
 
3374
    FORGET_Frame();
 
3375
 
 
3376
    cur_offset = FILE_Pos();
 
3377
    if ( FILE_Seek( new_offset ) ||
 
3378
         ( error = Load_PosRuleSet( &prs[n], stream ) ) != FT_Err_Ok )
 
3379
      goto Fail1;
 
3380
    (void)FILE_Seek( cur_offset );
 
3381
  }
 
3382
 
 
3383
  return FT_Err_Ok;
 
3384
 
 
3385
Fail1:
 
3386
  for ( m = 0; m < n; m++ )
 
3387
    Free_PosRuleSet( &prs[m], memory );
 
3388
 
 
3389
  FREE( prs );
 
3390
 
 
3391
Fail2:
 
3392
  _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
 
3393
  return error;
 
3394
}
 
3395
 
 
3396
 
 
3397
static void  Free_ContextPos1( HB_ContextPosFormat1*  cpf1,
 
3398
                            FT_Memory               memory )
 
3399
{
 
3400
  FT_UShort        n, count;
 
3401
 
 
3402
  HB_PosRuleSet*  prs;
 
3403
 
 
3404
 
 
3405
  if ( cpf1->PosRuleSet )
 
3406
  {
 
3407
    count = cpf1->PosRuleSetCount;
 
3408
    prs   = cpf1->PosRuleSet;
 
3409
 
 
3410
    for ( n = 0; n < count; n++ )
 
3411
      Free_PosRuleSet( &prs[n], memory );
 
3412
 
 
3413
    FREE( prs );
 
3414
  }
 
3415
 
 
3416
  _HB_OPEN_Free_Coverage( &cpf1->Coverage, memory );
 
3417
}
 
3418
 
 
3419
 
 
3420
/* PosClassRule */
 
3421
 
 
3422
static FT_Error  Load_PosClassRule( HB_ContextPosFormat2*  cpf2,
 
3423
                                    HB_PosClassRule*       pcr,
 
3424
                                    FT_Stream               stream )
 
3425
{
 
3426
  FT_Error  error;
 
3427
  FT_Memory memory = stream->memory;
 
3428
 
 
3429
  FT_UShort             n, count;
 
3430
 
 
3431
  FT_UShort*            c;
 
3432
  HB_PosLookupRecord*  plr;
 
3433
  FT_Bool*              d;
 
3434
 
 
3435
 
 
3436
  if ( ACCESS_Frame( 4L ) )
 
3437
    return error;
 
3438
 
 
3439
  pcr->GlyphCount = GET_UShort();
 
3440
  pcr->PosCount   = GET_UShort();
 
3441
 
 
3442
  FORGET_Frame();
 
3443
 
 
3444
  if ( pcr->GlyphCount > cpf2->MaxContextLength )
 
3445
    cpf2->MaxContextLength = pcr->GlyphCount;
 
3446
 
 
3447
  pcr->Class = NULL;
 
3448
 
 
3449
  count = pcr->GlyphCount - 1;        /* only GlyphCount - 1 elements */
 
3450
 
 
3451
  if ( ALLOC_ARRAY( pcr->Class, count, FT_UShort ) )
 
3452
    return error;
 
3453
 
 
3454
  c = pcr->Class;
 
3455
  d = cpf2->ClassDef.Defined;
 
3456
 
 
3457
  if ( ACCESS_Frame( count * 2L ) )
 
3458
    goto Fail2;
 
3459
 
 
3460
  for ( n = 0; n < count; n++ )
 
3461
  {
 
3462
    c[n] = GET_UShort();
 
3463
 
 
3464
    /* We check whether the specific class is used at all.  If not,
 
3465
       class 0 is used instead.                                     */
 
3466
 
 
3467
    if ( !d[c[n]] )
 
3468
      c[n] = 0;
 
3469
  }
 
3470
 
 
3471
  FORGET_Frame();
 
3472
 
 
3473
  pcr->PosLookupRecord = NULL;
 
3474
 
 
3475
  count = pcr->PosCount;
 
3476
 
 
3477
  if ( ALLOC_ARRAY( pcr->PosLookupRecord, count, HB_PosLookupRecord ) )
 
3478
    goto Fail2;
 
3479
 
 
3480
  plr = pcr->PosLookupRecord;
 
3481
 
 
3482
  if ( ACCESS_Frame( count * 4L ) )
 
3483
    goto Fail1;
 
3484
 
 
3485
  for ( n = 0; n < count; n++ )
 
3486
  {
 
3487
    plr[n].SequenceIndex   = GET_UShort();
 
3488
    plr[n].LookupListIndex = GET_UShort();
 
3489
  }
 
3490
 
 
3491
  FORGET_Frame();
 
3492
 
 
3493
  return FT_Err_Ok;
 
3494
 
 
3495
Fail1:
 
3496
  FREE( plr );
 
3497
 
 
3498
Fail2:
 
3499
  FREE( c );
 
3500
  return error;
 
3501
}
 
3502
 
 
3503
 
 
3504
static void  Free_PosClassRule( HB_PosClassRule*  pcr,
 
3505
                                FT_Memory          memory )
 
3506
{
 
3507
  FREE( pcr->PosLookupRecord );
 
3508
  FREE( pcr->Class );
 
3509
}
 
3510
 
 
3511
 
 
3512
/* PosClassSet */
 
3513
 
 
3514
static FT_Error  Load_PosClassSet( HB_ContextPosFormat2*  cpf2,
 
3515
                                   HB_PosClassSet*        pcs,
 
3516
                                   FT_Stream               stream )
 
3517
{
 
3518
  FT_Error  error;
 
3519
  FT_Memory memory = stream->memory;
 
3520
 
 
3521
  FT_UShort          n, m, count;
 
3522
  FT_ULong           cur_offset, new_offset, base_offset;
 
3523
 
 
3524
  HB_PosClassRule*  pcr;
 
3525
 
 
3526
 
 
3527
  base_offset = FILE_Pos();
 
3528
 
 
3529
  if ( ACCESS_Frame( 2L ) )
 
3530
    return error;
 
3531
 
 
3532
  count = pcs->PosClassRuleCount = GET_UShort();
 
3533
 
 
3534
  FORGET_Frame();
 
3535
 
 
3536
  pcs->PosClassRule = NULL;
 
3537
 
 
3538
  if ( ALLOC_ARRAY( pcs->PosClassRule, count, HB_PosClassRule ) )
 
3539
    return error;
 
3540
 
 
3541
  pcr = pcs->PosClassRule;
 
3542
 
 
3543
  for ( n = 0; n < count; n++ )
 
3544
  {
 
3545
    if ( ACCESS_Frame( 2L ) )
 
3546
      goto Fail;
 
3547
 
 
3548
    new_offset = GET_UShort() + base_offset;
 
3549
 
 
3550
    FORGET_Frame();
 
3551
 
 
3552
    cur_offset = FILE_Pos();
 
3553
    if ( FILE_Seek( new_offset ) ||
 
3554
         ( error = Load_PosClassRule( cpf2, &pcr[n],
 
3555
                                      stream ) ) != FT_Err_Ok )
 
3556
      goto Fail;
 
3557
    (void)FILE_Seek( cur_offset );
 
3558
  }
 
3559
 
 
3560
  return FT_Err_Ok;
 
3561
 
 
3562
Fail:
 
3563
  for ( m = 0; m < n; m++ )
 
3564
    Free_PosClassRule( &pcr[m], memory );
 
3565
 
 
3566
  FREE( pcr );
 
3567
  return error;
 
3568
}
 
3569
 
 
3570
 
 
3571
static void  Free_PosClassSet( HB_PosClassSet*  pcs,
 
3572
                               FT_Memory         memory )
 
3573
{
 
3574
  FT_UShort          n, count;
 
3575
 
 
3576
  HB_PosClassRule*  pcr;
 
3577
 
 
3578
 
 
3579
  if ( pcs->PosClassRule )
 
3580
  {
 
3581
    count = pcs->PosClassRuleCount;
 
3582
    pcr   = pcs->PosClassRule;
 
3583
 
 
3584
    for ( n = 0; n < count; n++ )
 
3585
      Free_PosClassRule( &pcr[n], memory );
 
3586
 
 
3587
    FREE( pcr );
 
3588
  }
 
3589
}
 
3590
 
 
3591
 
 
3592
/* ContextPosFormat2 */
 
3593
 
 
3594
static FT_Error  Load_ContextPos2( HB_ContextPosFormat2*  cpf2,
 
3595
                                   FT_Stream               stream )
 
3596
{
 
3597
  FT_Error  error;
 
3598
  FT_Memory memory = stream->memory;
 
3599
 
 
3600
  FT_UShort         n, m, count;
 
3601
  FT_ULong          cur_offset, new_offset, base_offset;
 
3602
 
 
3603
  HB_PosClassSet*  pcs;
 
3604
 
 
3605
 
 
3606
  base_offset = FILE_Pos() - 2;
 
3607
 
 
3608
  if ( ACCESS_Frame( 2L ) )
 
3609
    return error;
 
3610
 
 
3611
  new_offset = GET_UShort() + base_offset;
 
3612
 
 
3613
  FORGET_Frame();
 
3614
 
 
3615
  cur_offset = FILE_Pos();
 
3616
  if ( FILE_Seek( new_offset ) ||
 
3617
       ( error = _HB_OPEN_Load_Coverage( &cpf2->Coverage, stream ) ) != FT_Err_Ok )
 
3618
    return error;
 
3619
  (void)FILE_Seek( cur_offset );
 
3620
 
 
3621
  if ( ACCESS_Frame( 4L ) )
 
3622
    goto Fail3;
 
3623
 
 
3624
  new_offset = GET_UShort() + base_offset;
 
3625
 
 
3626
  /* `PosClassSetCount' is the upper limit for class values, thus we
 
3627
     read it now to make an additional safety check.                 */
 
3628
 
 
3629
  count = cpf2->PosClassSetCount = GET_UShort();
 
3630
 
 
3631
  FORGET_Frame();
 
3632
 
 
3633
  cur_offset = FILE_Pos();
 
3634
  if ( FILE_Seek( new_offset ) ||
 
3635
       ( error = _HB_OPEN_Load_ClassDefinition( &cpf2->ClassDef, count,
 
3636
                                       stream ) ) != FT_Err_Ok )
 
3637
    goto Fail3;
 
3638
  (void)FILE_Seek( cur_offset );
 
3639
 
 
3640
  cpf2->PosClassSet      = NULL;
 
3641
  cpf2->MaxContextLength = 0;
 
3642
 
 
3643
  if ( ALLOC_ARRAY( cpf2->PosClassSet, count, HB_PosClassSet ) )
 
3644
    goto Fail2;
 
3645
 
 
3646
  pcs = cpf2->PosClassSet;
 
3647
 
 
3648
  for ( n = 0; n < count; n++ )
 
3649
  {
 
3650
    if ( ACCESS_Frame( 2L ) )
 
3651
      goto Fail1;
 
3652
 
 
3653
    new_offset = GET_UShort() + base_offset;
 
3654
 
 
3655
    FORGET_Frame();
 
3656
 
 
3657
    if ( new_offset != base_offset )      /* not a NULL offset */
 
3658
    {
 
3659
      cur_offset = FILE_Pos();
 
3660
      if ( FILE_Seek( new_offset ) ||
 
3661
           ( error = Load_PosClassSet( cpf2, &pcs[n],
 
3662
                                       stream ) ) != FT_Err_Ok )
 
3663
        goto Fail1;
 
3664
      (void)FILE_Seek( cur_offset );
 
3665
    }
 
3666
    else
 
3667
    {
 
3668
      /* we create a PosClassSet table with no entries */
 
3669
 
 
3670
      cpf2->PosClassSet[n].PosClassRuleCount = 0;
 
3671
      cpf2->PosClassSet[n].PosClassRule      = NULL;
 
3672
    }
 
3673
  }
 
3674
 
 
3675
  return FT_Err_Ok;
 
3676
 
 
3677
Fail1:
 
3678
  for ( m = 0; m < n; n++ )
 
3679
    Free_PosClassSet( &pcs[m], memory );
 
3680
 
 
3681
  FREE( pcs );
 
3682
 
 
3683
Fail2:
 
3684
  _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
 
3685
 
 
3686
Fail3:
 
3687
  _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
 
3688
  return error;
 
3689
}
 
3690
 
 
3691
 
 
3692
static void  Free_ContextPos2( HB_ContextPosFormat2*  cpf2,
 
3693
                            FT_Memory               memory )
 
3694
{
 
3695
  FT_UShort         n, count;
 
3696
 
 
3697
  HB_PosClassSet*  pcs;
 
3698
 
 
3699
 
 
3700
  if ( cpf2->PosClassSet )
 
3701
  {
 
3702
    count = cpf2->PosClassSetCount;
 
3703
    pcs   = cpf2->PosClassSet;
 
3704
 
 
3705
    for ( n = 0; n < count; n++ )
 
3706
      Free_PosClassSet( &pcs[n], memory );
 
3707
 
 
3708
    FREE( pcs );
 
3709
  }
 
3710
 
 
3711
  _HB_OPEN_Free_ClassDefinition( &cpf2->ClassDef, memory );
 
3712
  _HB_OPEN_Free_Coverage( &cpf2->Coverage, memory );
 
3713
}
 
3714
 
 
3715
 
 
3716
/* ContextPosFormat3 */
 
3717
 
 
3718
static FT_Error  Load_ContextPos3( HB_ContextPosFormat3*  cpf3,
 
3719
                                   FT_Stream               stream )
 
3720
{
 
3721
  FT_Error  error;
 
3722
  FT_Memory memory = stream->memory;
 
3723
 
 
3724
  FT_UShort             n, count;
 
3725
  FT_ULong              cur_offset, new_offset, base_offset;
 
3726
 
 
3727
  HB_Coverage*         c;
 
3728
  HB_PosLookupRecord*  plr;
 
3729
 
 
3730
 
 
3731
  base_offset = FILE_Pos() - 2L;
 
3732
 
 
3733
  if ( ACCESS_Frame( 4L ) )
 
3734
    return error;
 
3735
 
 
3736
  cpf3->GlyphCount = GET_UShort();
 
3737
  cpf3->PosCount   = GET_UShort();
 
3738
 
 
3739
  FORGET_Frame();
 
3740
 
 
3741
  cpf3->Coverage = NULL;
 
3742
 
 
3743
  count = cpf3->GlyphCount;
 
3744
 
 
3745
  if ( ALLOC_ARRAY( cpf3->Coverage, count, HB_Coverage ) )
 
3746
    return error;
 
3747
 
 
3748
  c = cpf3->Coverage;
 
3749
 
 
3750
  for ( n = 0; n < count; n++ )
 
3751
  {
 
3752
    if ( ACCESS_Frame( 2L ) )
 
3753
      goto Fail2;
 
3754
 
 
3755
    new_offset = GET_UShort() + base_offset;
 
3756
 
 
3757
    FORGET_Frame();
 
3758
 
 
3759
    cur_offset = FILE_Pos();
 
3760
    if ( FILE_Seek( new_offset ) ||
 
3761
         ( error = _HB_OPEN_Load_Coverage( &c[n], stream ) ) != FT_Err_Ok )
 
3762
      goto Fail2;
 
3763
    (void)FILE_Seek( cur_offset );
 
3764
  }
 
3765
 
 
3766
  cpf3->PosLookupRecord = NULL;
 
3767
 
 
3768
  count = cpf3->PosCount;
 
3769
 
 
3770
  if ( ALLOC_ARRAY( cpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
 
3771
    goto Fail2;
 
3772
 
 
3773
  plr = cpf3->PosLookupRecord;
 
3774
 
 
3775
  if ( ACCESS_Frame( count * 4L ) )
 
3776
    goto Fail1;
 
3777
 
 
3778
  for ( n = 0; n < count; n++ )
 
3779
  {
 
3780
    plr[n].SequenceIndex   = GET_UShort();
 
3781
    plr[n].LookupListIndex = GET_UShort();
 
3782
  }
 
3783
 
 
3784
  FORGET_Frame();
 
3785
 
 
3786
  return FT_Err_Ok;
 
3787
 
 
3788
Fail1:
 
3789
  FREE( plr );
 
3790
 
 
3791
Fail2:
 
3792
  for ( n = 0; n < count; n++ )
 
3793
    _HB_OPEN_Free_Coverage( &c[n], memory );
 
3794
 
 
3795
  FREE( c );
 
3796
  return error;
 
3797
}
 
3798
 
 
3799
 
 
3800
static void  Free_ContextPos3( HB_ContextPosFormat3*  cpf3,
 
3801
                            FT_Memory               memory )
 
3802
{
 
3803
  FT_UShort      n, count;
 
3804
 
 
3805
  HB_Coverage*  c;
 
3806
 
 
3807
 
 
3808
  FREE( cpf3->PosLookupRecord );
 
3809
 
 
3810
  if ( cpf3->Coverage )
 
3811
  {
 
3812
    count = cpf3->GlyphCount;
 
3813
    c     = cpf3->Coverage;
 
3814
 
 
3815
    for ( n = 0; n < count; n++ )
 
3816
      _HB_OPEN_Free_Coverage( &c[n], memory );
 
3817
 
 
3818
    FREE( c );
 
3819
  }
 
3820
}
 
3821
 
 
3822
 
 
3823
/* ContextPos */
 
3824
 
 
3825
static FT_Error  Load_ContextPos( HB_GPOS_SubTable* st,
 
3826
                                  FT_Stream        stream )
 
3827
{
 
3828
  FT_Error  error;
 
3829
  HB_ContextPos*   cp = &st->context;
 
3830
 
 
3831
 
 
3832
  if ( ACCESS_Frame( 2L ) )
 
3833
    return error;
 
3834
 
 
3835
  cp->PosFormat = GET_UShort();
 
3836
 
 
3837
  FORGET_Frame();
 
3838
 
 
3839
  switch ( cp->PosFormat )
 
3840
  {
 
3841
  case 1:
 
3842
    return Load_ContextPos1( &cp->cpf.cpf1, stream );
 
3843
 
 
3844
  case 2:
 
3845
    return Load_ContextPos2( &cp->cpf.cpf2, stream );
 
3846
 
 
3847
  case 3:
 
3848
    return Load_ContextPos3( &cp->cpf.cpf3, stream );
 
3849
 
 
3850
  default:
 
3851
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
3852
  }
 
3853
 
 
3854
  return FT_Err_Ok;               /* never reached */
 
3855
}
 
3856
 
 
3857
 
 
3858
static void  Free_ContextPos( HB_GPOS_SubTable* st,
 
3859
                              FT_Memory        memory )
 
3860
{
 
3861
  HB_ContextPos*   cp = &st->context;
 
3862
 
 
3863
  switch ( cp->PosFormat )
 
3864
  {
 
3865
  case 1:
 
3866
    Free_ContextPos1( &cp->cpf.cpf1, memory );
 
3867
    break;
 
3868
 
 
3869
  case 2:
 
3870
    Free_ContextPos2( &cp->cpf.cpf2, memory );
 
3871
    break;
 
3872
 
 
3873
  case 3:
 
3874
    Free_ContextPos3( &cp->cpf.cpf3, memory );
 
3875
    break;
 
3876
  }
 
3877
}
 
3878
 
 
3879
 
 
3880
static FT_Error  Lookup_ContextPos1( GPOS_Instance*          gpi,
 
3881
                                     HB_ContextPosFormat1*  cpf1,
 
3882
                                     HB_Buffer              buffer,
 
3883
                                     FT_UShort               flags,
 
3884
                                     FT_UShort               context_length,
 
3885
                                     int                     nesting_level )
 
3886
{
 
3887
  FT_UShort        index, property;
 
3888
  FT_UShort        i, j, k, numpr;
 
3889
  FT_Error         error;
 
3890
  HB_GPOSHeader*  gpos = gpi->gpos;
 
3891
 
 
3892
  HB_PosRule*     pr;
 
3893
  HB_GDEFHeader*  gdef;
 
3894
 
 
3895
 
 
3896
  gdef = gpos->gdef;
 
3897
 
 
3898
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
3899
    return error;
 
3900
 
 
3901
  error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
 
3902
  if ( error )
 
3903
    return error;
 
3904
 
 
3905
  pr    = cpf1->PosRuleSet[index].PosRule;
 
3906
  numpr = cpf1->PosRuleSet[index].PosRuleCount;
 
3907
 
 
3908
  for ( k = 0; k < numpr; k++ )
 
3909
  {
 
3910
    if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount )
 
3911
      goto next_posrule;
 
3912
 
 
3913
    if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length )
 
3914
      goto next_posrule;                       /* context is too long */
 
3915
 
 
3916
    for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
 
3917
    {
 
3918
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
3919
      {
 
3920
        if ( error && error != HB_Err_Not_Covered )
 
3921
          return error;
 
3922
 
 
3923
        if ( j + pr[k].GlyphCount - i == (FT_Long)buffer->in_length )
 
3924
          goto next_posrule;
 
3925
        j++;
 
3926
      }
 
3927
 
 
3928
      if ( IN_GLYPH( j ) != pr[k].Input[i - 1] )
 
3929
        goto next_posrule;
 
3930
    }
 
3931
 
 
3932
    return Do_ContextPos( gpi, pr[k].GlyphCount,
 
3933
                          pr[k].PosCount, pr[k].PosLookupRecord,
 
3934
                          buffer,
 
3935
                          nesting_level );
 
3936
 
 
3937
    next_posrule:
 
3938
      ;
 
3939
  }
 
3940
 
 
3941
  return HB_Err_Not_Covered;
 
3942
}
 
3943
 
 
3944
 
 
3945
static FT_Error  Lookup_ContextPos2( GPOS_Instance*          gpi,
 
3946
                                     HB_ContextPosFormat2*  cpf2,
 
3947
                                     HB_Buffer              buffer,
 
3948
                                     FT_UShort               flags,
 
3949
                                     FT_UShort               context_length,
 
3950
                                     int                     nesting_level )
 
3951
{
 
3952
  FT_UShort          index, property;
 
3953
  FT_Error           error;
 
3954
  FT_Memory          memory = gpi->face->memory;
 
3955
  FT_UShort          i, j, k, known_classes;
 
3956
 
 
3957
  FT_UShort*         classes;
 
3958
  FT_UShort*         cl;
 
3959
  HB_GPOSHeader*    gpos = gpi->gpos;
 
3960
 
 
3961
  HB_PosClassSet*   pcs;
 
3962
  HB_PosClassRule*  pr;
 
3963
  HB_GDEFHeader*    gdef;
 
3964
 
 
3965
 
 
3966
  gdef = gpos->gdef;
 
3967
 
 
3968
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
3969
    return error;
 
3970
 
 
3971
  /* Note: The coverage table in format 2 doesn't give an index into
 
3972
           anything.  It just lets us know whether or not we need to
 
3973
           do any lookup at all.                                     */
 
3974
 
 
3975
  error = _HB_OPEN_Coverage_Index( &cpf2->Coverage, IN_CURGLYPH(), &index );
 
3976
  if ( error )
 
3977
    return error;
 
3978
 
 
3979
  if ( ALLOC_ARRAY( classes, cpf2->MaxContextLength, FT_UShort ) )
 
3980
    return error;
 
3981
 
 
3982
  error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_CURGLYPH(),
 
3983
                     &classes[0], NULL );
 
3984
  if ( error && error != HB_Err_Not_Covered )
 
3985
    goto End;
 
3986
  known_classes = 0;
 
3987
 
 
3988
  pcs = &cpf2->PosClassSet[classes[0]];
 
3989
  if ( !pcs )
 
3990
  {
 
3991
    error = HB_Err_Invalid_GPOS_SubTable;
 
3992
    goto End;
 
3993
  }
 
3994
 
 
3995
  for ( k = 0; k < pcs->PosClassRuleCount; k++ )
 
3996
  {
 
3997
    pr = &pcs->PosClassRule[k];
 
3998
 
 
3999
    if ( context_length != 0xFFFF && context_length < pr->GlyphCount )
 
4000
      goto next_posclassrule;
 
4001
 
 
4002
    if ( buffer->in_pos + pr->GlyphCount > buffer->in_length )
 
4003
      goto next_posclassrule;                /* context is too long */
 
4004
 
 
4005
    cl   = pr->Class;
 
4006
 
 
4007
    /* Start at 1 because [0] is implied */
 
4008
 
 
4009
    for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
 
4010
    {
 
4011
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
4012
      {
 
4013
        if ( error && error != HB_Err_Not_Covered )
 
4014
          goto End;
 
4015
 
 
4016
        if ( j + pr->GlyphCount - i == (FT_Long)buffer->in_length )
 
4017
          goto next_posclassrule;
 
4018
        j++;
 
4019
      }
 
4020
 
 
4021
      if ( i > known_classes )
 
4022
      {
 
4023
        /* Keeps us from having to do this for each rule */
 
4024
 
 
4025
        error = _HB_OPEN_Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL );
 
4026
        if ( error && error != HB_Err_Not_Covered )
 
4027
          goto End;
 
4028
        known_classes = i;
 
4029
      }
 
4030
 
 
4031
      if ( cl[i - 1] != classes[i] )
 
4032
        goto next_posclassrule;
 
4033
    }
 
4034
 
 
4035
    error = Do_ContextPos( gpi, pr->GlyphCount,
 
4036
                           pr->PosCount, pr->PosLookupRecord,
 
4037
                           buffer,
 
4038
                           nesting_level );
 
4039
    goto End;
 
4040
 
 
4041
  next_posclassrule:
 
4042
    ;
 
4043
  }
 
4044
 
 
4045
  error = HB_Err_Not_Covered;
 
4046
 
 
4047
End:
 
4048
  FREE( classes );
 
4049
  return error;
 
4050
}
 
4051
 
 
4052
 
 
4053
static FT_Error  Lookup_ContextPos3( GPOS_Instance*          gpi,
 
4054
                                     HB_ContextPosFormat3*  cpf3,
 
4055
                                     HB_Buffer              buffer,
 
4056
                                     FT_UShort               flags,
 
4057
                                     FT_UShort               context_length,
 
4058
                                     int                     nesting_level )
 
4059
{
 
4060
  FT_Error         error;
 
4061
  FT_UShort        index, i, j, property;
 
4062
  HB_GPOSHeader*  gpos = gpi->gpos;
 
4063
 
 
4064
  HB_Coverage*    c;
 
4065
  HB_GDEFHeader*  gdef;
 
4066
 
 
4067
 
 
4068
  gdef = gpos->gdef;
 
4069
 
 
4070
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
4071
    return error;
 
4072
 
 
4073
  if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
 
4074
    return HB_Err_Not_Covered;
 
4075
 
 
4076
  if ( buffer->in_pos + cpf3->GlyphCount > buffer->in_length )
 
4077
    return HB_Err_Not_Covered;         /* context is too long */
 
4078
 
 
4079
  c    = cpf3->Coverage;
 
4080
 
 
4081
  for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
 
4082
  {
 
4083
    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
4084
    {
 
4085
      if ( error && error != HB_Err_Not_Covered )
 
4086
        return error;
 
4087
 
 
4088
      if ( j + cpf3->GlyphCount - i == (FT_Long)buffer->in_length )
 
4089
        return HB_Err_Not_Covered;
 
4090
      j++;
 
4091
    }
 
4092
 
 
4093
    error = _HB_OPEN_Coverage_Index( &c[i], IN_GLYPH( j ), &index );
 
4094
    if ( error )
 
4095
      return error;
 
4096
  }
 
4097
 
 
4098
  return Do_ContextPos( gpi, cpf3->GlyphCount,
 
4099
                        cpf3->PosCount, cpf3->PosLookupRecord,
 
4100
                        buffer,
 
4101
                        nesting_level );
 
4102
}
 
4103
 
 
4104
 
 
4105
static FT_Error  Lookup_ContextPos( GPOS_Instance*    gpi,
 
4106
                                    HB_GPOS_SubTable* st,
 
4107
                                    HB_Buffer        buffer,
 
4108
                                    FT_UShort         flags,
 
4109
                                    FT_UShort         context_length,
 
4110
                                    int               nesting_level )
 
4111
{
 
4112
  HB_ContextPos*   cp = &st->context;
 
4113
 
 
4114
  switch ( cp->PosFormat )
 
4115
  {
 
4116
  case 1:
 
4117
    return Lookup_ContextPos1( gpi, &cp->cpf.cpf1, buffer,
 
4118
                               flags, context_length, nesting_level );
 
4119
 
 
4120
  case 2:
 
4121
    return Lookup_ContextPos2( gpi, &cp->cpf.cpf2, buffer,
 
4122
                               flags, context_length, nesting_level );
 
4123
 
 
4124
  case 3:
 
4125
    return Lookup_ContextPos3( gpi, &cp->cpf.cpf3, buffer,
 
4126
                               flags, context_length, nesting_level );
 
4127
 
 
4128
  default:
 
4129
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
4130
  }
 
4131
 
 
4132
  return FT_Err_Ok;               /* never reached */
 
4133
}
 
4134
 
 
4135
 
 
4136
/* LookupType 8 */
 
4137
 
 
4138
/* ChainPosRule */
 
4139
 
 
4140
static FT_Error  Load_ChainPosRule( HB_ChainPosRule*  cpr,
 
4141
                                    FT_Stream          stream )
 
4142
{
 
4143
  FT_Error  error;
 
4144
  FT_Memory memory = stream->memory;
 
4145
 
 
4146
  FT_UShort             n, count;
 
4147
  FT_UShort*            b;
 
4148
  FT_UShort*            i;
 
4149
  FT_UShort*            l;
 
4150
 
 
4151
  HB_PosLookupRecord*  plr;
 
4152
 
 
4153
 
 
4154
  if ( ACCESS_Frame( 2L ) )
 
4155
    return error;
 
4156
 
 
4157
  cpr->BacktrackGlyphCount = GET_UShort();
 
4158
 
 
4159
  FORGET_Frame();
 
4160
 
 
4161
  cpr->Backtrack = NULL;
 
4162
 
 
4163
  count = cpr->BacktrackGlyphCount;
 
4164
 
 
4165
  if ( ALLOC_ARRAY( cpr->Backtrack, count, FT_UShort ) )
 
4166
    return error;
 
4167
 
 
4168
  b = cpr->Backtrack;
 
4169
 
 
4170
  if ( ACCESS_Frame( count * 2L ) )
 
4171
    goto Fail4;
 
4172
 
 
4173
  for ( n = 0; n < count; n++ )
 
4174
    b[n] = GET_UShort();
 
4175
 
 
4176
  FORGET_Frame();
 
4177
 
 
4178
  if ( ACCESS_Frame( 2L ) )
 
4179
    goto Fail4;
 
4180
 
 
4181
  cpr->InputGlyphCount = GET_UShort();
 
4182
 
 
4183
  FORGET_Frame();
 
4184
 
 
4185
  cpr->Input = NULL;
 
4186
 
 
4187
  count = cpr->InputGlyphCount - 1;  /* only InputGlyphCount - 1 elements */
 
4188
 
 
4189
  if ( ALLOC_ARRAY( cpr->Input, count, FT_UShort ) )
 
4190
    goto Fail4;
 
4191
 
 
4192
  i = cpr->Input;
 
4193
 
 
4194
  if ( ACCESS_Frame( count * 2L ) )
 
4195
    goto Fail3;
 
4196
 
 
4197
  for ( n = 0; n < count; n++ )
 
4198
    i[n] = GET_UShort();
 
4199
 
 
4200
  FORGET_Frame();
 
4201
 
 
4202
  if ( ACCESS_Frame( 2L ) )
 
4203
    goto Fail3;
 
4204
 
 
4205
  cpr->LookaheadGlyphCount = GET_UShort();
 
4206
 
 
4207
  FORGET_Frame();
 
4208
 
 
4209
  cpr->Lookahead = NULL;
 
4210
 
 
4211
  count = cpr->LookaheadGlyphCount;
 
4212
 
 
4213
  if ( ALLOC_ARRAY( cpr->Lookahead, count, FT_UShort ) )
 
4214
    goto Fail3;
 
4215
 
 
4216
  l = cpr->Lookahead;
 
4217
 
 
4218
  if ( ACCESS_Frame( count * 2L ) )
 
4219
    goto Fail2;
 
4220
 
 
4221
  for ( n = 0; n < count; n++ )
 
4222
    l[n] = GET_UShort();
 
4223
 
 
4224
  FORGET_Frame();
 
4225
 
 
4226
  if ( ACCESS_Frame( 2L ) )
 
4227
    goto Fail2;
 
4228
 
 
4229
  cpr->PosCount = GET_UShort();
 
4230
 
 
4231
  FORGET_Frame();
 
4232
 
 
4233
  cpr->PosLookupRecord = NULL;
 
4234
 
 
4235
  count = cpr->PosCount;
 
4236
 
 
4237
  if ( ALLOC_ARRAY( cpr->PosLookupRecord, count, HB_PosLookupRecord ) )
 
4238
    goto Fail2;
 
4239
 
 
4240
  plr = cpr->PosLookupRecord;
 
4241
 
 
4242
  if ( ACCESS_Frame( count * 4L ) )
 
4243
    goto Fail1;
 
4244
 
 
4245
  for ( n = 0; n < count; n++ )
 
4246
  {
 
4247
    plr[n].SequenceIndex   = GET_UShort();
 
4248
    plr[n].LookupListIndex = GET_UShort();
 
4249
  }
 
4250
 
 
4251
  FORGET_Frame();
 
4252
 
 
4253
  return FT_Err_Ok;
 
4254
 
 
4255
Fail1:
 
4256
  FREE( plr );
 
4257
 
 
4258
Fail2:
 
4259
  FREE( l );
 
4260
 
 
4261
Fail3:
 
4262
  FREE( i );
 
4263
 
 
4264
Fail4:
 
4265
  FREE( b );
 
4266
  return error;
 
4267
}
 
4268
 
 
4269
 
 
4270
static void  Free_ChainPosRule( HB_ChainPosRule*  cpr,
 
4271
                                FT_Memory          memory )
 
4272
{
 
4273
  FREE( cpr->PosLookupRecord );
 
4274
  FREE( cpr->Lookahead );
 
4275
  FREE( cpr->Input );
 
4276
  FREE( cpr->Backtrack );
 
4277
}
 
4278
 
 
4279
 
 
4280
/* ChainPosRuleSet */
 
4281
 
 
4282
static FT_Error  Load_ChainPosRuleSet( HB_ChainPosRuleSet*  cprs,
 
4283
                                       FT_Stream             stream )
 
4284
{
 
4285
  FT_Error  error;
 
4286
  FT_Memory memory = stream->memory;
 
4287
 
 
4288
  FT_UShort          n, m, count;
 
4289
  FT_ULong           cur_offset, new_offset, base_offset;
 
4290
 
 
4291
  HB_ChainPosRule*  cpr;
 
4292
 
 
4293
 
 
4294
  base_offset = FILE_Pos();
 
4295
 
 
4296
  if ( ACCESS_Frame( 2L ) )
 
4297
    return error;
 
4298
 
 
4299
  count = cprs->ChainPosRuleCount = GET_UShort();
 
4300
 
 
4301
  FORGET_Frame();
 
4302
 
 
4303
  cprs->ChainPosRule = NULL;
 
4304
 
 
4305
  if ( ALLOC_ARRAY( cprs->ChainPosRule, count, HB_ChainPosRule ) )
 
4306
    return error;
 
4307
 
 
4308
  cpr = cprs->ChainPosRule;
 
4309
 
 
4310
  for ( n = 0; n < count; n++ )
 
4311
  {
 
4312
    if ( ACCESS_Frame( 2L ) )
 
4313
      goto Fail;
 
4314
 
 
4315
    new_offset = GET_UShort() + base_offset;
 
4316
 
 
4317
    FORGET_Frame();
 
4318
 
 
4319
    cur_offset = FILE_Pos();
 
4320
    if ( FILE_Seek( new_offset ) ||
 
4321
         ( error = Load_ChainPosRule( &cpr[n], stream ) ) != FT_Err_Ok )
 
4322
      goto Fail;
 
4323
    (void)FILE_Seek( cur_offset );
 
4324
  }
 
4325
 
 
4326
  return FT_Err_Ok;
 
4327
 
 
4328
Fail:
 
4329
  for ( m = 0; m < n; m++ )
 
4330
    Free_ChainPosRule( &cpr[m], memory );
 
4331
 
 
4332
  FREE( cpr );
 
4333
  return error;
 
4334
}
 
4335
 
 
4336
 
 
4337
static void  Free_ChainPosRuleSet( HB_ChainPosRuleSet*  cprs,
 
4338
                                   FT_Memory             memory )
 
4339
{
 
4340
  FT_UShort          n, count;
 
4341
 
 
4342
  HB_ChainPosRule*  cpr;
 
4343
 
 
4344
 
 
4345
  if ( cprs->ChainPosRule )
 
4346
  {
 
4347
    count = cprs->ChainPosRuleCount;
 
4348
    cpr   = cprs->ChainPosRule;
 
4349
 
 
4350
    for ( n = 0; n < count; n++ )
 
4351
      Free_ChainPosRule( &cpr[n], memory );
 
4352
 
 
4353
    FREE( cpr );
 
4354
  }
 
4355
}
 
4356
 
 
4357
 
 
4358
/* ChainContextPosFormat1 */
 
4359
 
 
4360
static FT_Error  Load_ChainContextPos1( HB_ChainContextPosFormat1*  ccpf1,
 
4361
                                        FT_Stream                    stream )
 
4362
{
 
4363
  FT_Error  error;
 
4364
  FT_Memory memory = stream->memory;
 
4365
 
 
4366
  FT_UShort             n, m, count;
 
4367
  FT_ULong              cur_offset, new_offset, base_offset;
 
4368
 
 
4369
  HB_ChainPosRuleSet*  cprs;
 
4370
 
 
4371
 
 
4372
  base_offset = FILE_Pos() - 2L;
 
4373
 
 
4374
  if ( ACCESS_Frame( 2L ) )
 
4375
    return error;
 
4376
 
 
4377
  new_offset = GET_UShort() + base_offset;
 
4378
 
 
4379
  FORGET_Frame();
 
4380
 
 
4381
  cur_offset = FILE_Pos();
 
4382
  if ( FILE_Seek( new_offset ) ||
 
4383
       ( error = _HB_OPEN_Load_Coverage( &ccpf1->Coverage, stream ) ) != FT_Err_Ok )
 
4384
    return error;
 
4385
  (void)FILE_Seek( cur_offset );
 
4386
 
 
4387
  if ( ACCESS_Frame( 2L ) )
 
4388
    goto Fail2;
 
4389
 
 
4390
  count = ccpf1->ChainPosRuleSetCount = GET_UShort();
 
4391
 
 
4392
  FORGET_Frame();
 
4393
 
 
4394
  ccpf1->ChainPosRuleSet = NULL;
 
4395
 
 
4396
  if ( ALLOC_ARRAY( ccpf1->ChainPosRuleSet, count, HB_ChainPosRuleSet ) )
 
4397
    goto Fail2;
 
4398
 
 
4399
  cprs = ccpf1->ChainPosRuleSet;
 
4400
 
 
4401
  for ( n = 0; n < count; n++ )
 
4402
  {
 
4403
    if ( ACCESS_Frame( 2L ) )
 
4404
      goto Fail1;
 
4405
 
 
4406
    new_offset = GET_UShort() + base_offset;
 
4407
 
 
4408
    FORGET_Frame();
 
4409
 
 
4410
    cur_offset = FILE_Pos();
 
4411
    if ( FILE_Seek( new_offset ) ||
 
4412
         ( error = Load_ChainPosRuleSet( &cprs[n], stream ) ) != FT_Err_Ok )
 
4413
      goto Fail1;
 
4414
    (void)FILE_Seek( cur_offset );
 
4415
  }
 
4416
 
 
4417
  return FT_Err_Ok;
 
4418
 
 
4419
Fail1:
 
4420
  for ( m = 0; m < n; m++ )
 
4421
    Free_ChainPosRuleSet( &cprs[m], memory );
 
4422
 
 
4423
  FREE( cprs );
 
4424
 
 
4425
Fail2:
 
4426
  _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
 
4427
  return error;
 
4428
}
 
4429
 
 
4430
 
 
4431
static void  Free_ChainContextPos1( HB_ChainContextPosFormat1*  ccpf1,
 
4432
                                 FT_Memory                    memory )
 
4433
{
 
4434
  FT_UShort             n, count;
 
4435
 
 
4436
  HB_ChainPosRuleSet*  cprs;
 
4437
 
 
4438
 
 
4439
  if ( ccpf1->ChainPosRuleSet )
 
4440
  {
 
4441
    count = ccpf1->ChainPosRuleSetCount;
 
4442
    cprs  = ccpf1->ChainPosRuleSet;
 
4443
 
 
4444
    for ( n = 0; n < count; n++ )
 
4445
      Free_ChainPosRuleSet( &cprs[n], memory );
 
4446
 
 
4447
    FREE( cprs );
 
4448
  }
 
4449
 
 
4450
  _HB_OPEN_Free_Coverage( &ccpf1->Coverage, memory );
 
4451
}
 
4452
 
 
4453
 
 
4454
/* ChainPosClassRule */
 
4455
 
 
4456
static FT_Error  Load_ChainPosClassRule(
 
4457
                   HB_ChainContextPosFormat2*  ccpf2,
 
4458
                   HB_ChainPosClassRule*       cpcr,
 
4459
                   FT_Stream                    stream )
 
4460
{
 
4461
  FT_Error  error;
 
4462
  FT_Memory memory = stream->memory;
 
4463
 
 
4464
  FT_UShort             n, count;
 
4465
 
 
4466
  FT_UShort*            b;
 
4467
  FT_UShort*            i;
 
4468
  FT_UShort*            l;
 
4469
  HB_PosLookupRecord*  plr;
 
4470
  FT_Bool*              d;
 
4471
 
 
4472
 
 
4473
  if ( ACCESS_Frame( 2L ) )
 
4474
    return error;
 
4475
 
 
4476
  cpcr->BacktrackGlyphCount = GET_UShort();
 
4477
 
 
4478
  FORGET_Frame();
 
4479
 
 
4480
  if ( cpcr->BacktrackGlyphCount > ccpf2->MaxBacktrackLength )
 
4481
    ccpf2->MaxBacktrackLength = cpcr->BacktrackGlyphCount;
 
4482
 
 
4483
  cpcr->Backtrack = NULL;
 
4484
 
 
4485
  count = cpcr->BacktrackGlyphCount;
 
4486
 
 
4487
  if ( ALLOC_ARRAY( cpcr->Backtrack, count, FT_UShort ) )
 
4488
    return error;
 
4489
 
 
4490
  b = cpcr->Backtrack;
 
4491
  d = ccpf2->BacktrackClassDef.Defined;
 
4492
 
 
4493
  if ( ACCESS_Frame( count * 2L ) )
 
4494
    goto Fail4;
 
4495
 
 
4496
  for ( n = 0; n < count; n++ )
 
4497
  {
 
4498
    b[n] = GET_UShort();
 
4499
 
 
4500
    /* We check whether the specific class is used at all.  If not,
 
4501
       class 0 is used instead.                                     */
 
4502
 
 
4503
    if ( !d[b[n]] )
 
4504
      b[n] = 0;
 
4505
  }
 
4506
 
 
4507
  FORGET_Frame();
 
4508
 
 
4509
  if ( ACCESS_Frame( 2L ) )
 
4510
    goto Fail4;
 
4511
 
 
4512
  cpcr->InputGlyphCount = GET_UShort();
 
4513
 
 
4514
  if ( cpcr->InputGlyphCount > ccpf2->MaxInputLength )
 
4515
    ccpf2->MaxInputLength = cpcr->InputGlyphCount;
 
4516
 
 
4517
  FORGET_Frame();
 
4518
 
 
4519
  cpcr->Input = NULL;
 
4520
 
 
4521
  count = cpcr->InputGlyphCount - 1; /* only InputGlyphCount - 1 elements */
 
4522
 
 
4523
  if ( ALLOC_ARRAY( cpcr->Input, count, FT_UShort ) )
 
4524
    goto Fail4;
 
4525
 
 
4526
  i = cpcr->Input;
 
4527
  d = ccpf2->InputClassDef.Defined;
 
4528
 
 
4529
  if ( ACCESS_Frame( count * 2L ) )
 
4530
    goto Fail3;
 
4531
 
 
4532
  for ( n = 0; n < count; n++ )
 
4533
  {
 
4534
    i[n] = GET_UShort();
 
4535
 
 
4536
    if ( !d[i[n]] )
 
4537
      i[n] = 0;
 
4538
  }
 
4539
 
 
4540
  FORGET_Frame();
 
4541
 
 
4542
  if ( ACCESS_Frame( 2L ) )
 
4543
    goto Fail3;
 
4544
 
 
4545
  cpcr->LookaheadGlyphCount = GET_UShort();
 
4546
 
 
4547
  FORGET_Frame();
 
4548
 
 
4549
  if ( cpcr->LookaheadGlyphCount > ccpf2->MaxLookaheadLength )
 
4550
    ccpf2->MaxLookaheadLength = cpcr->LookaheadGlyphCount;
 
4551
 
 
4552
  cpcr->Lookahead = NULL;
 
4553
 
 
4554
  count = cpcr->LookaheadGlyphCount;
 
4555
 
 
4556
  if ( ALLOC_ARRAY( cpcr->Lookahead, count, FT_UShort ) )
 
4557
    goto Fail3;
 
4558
 
 
4559
  l = cpcr->Lookahead;
 
4560
  d = ccpf2->LookaheadClassDef.Defined;
 
4561
 
 
4562
  if ( ACCESS_Frame( count * 2L ) )
 
4563
    goto Fail2;
 
4564
 
 
4565
  for ( n = 0; n < count; n++ )
 
4566
  {
 
4567
    l[n] = GET_UShort();
 
4568
 
 
4569
    if ( !d[l[n]] )
 
4570
      l[n] = 0;
 
4571
  }
 
4572
 
 
4573
  FORGET_Frame();
 
4574
 
 
4575
  if ( ACCESS_Frame( 2L ) )
 
4576
    goto Fail2;
 
4577
 
 
4578
  cpcr->PosCount = GET_UShort();
 
4579
 
 
4580
  FORGET_Frame();
 
4581
 
 
4582
  cpcr->PosLookupRecord = NULL;
 
4583
 
 
4584
  count = cpcr->PosCount;
 
4585
 
 
4586
  if ( ALLOC_ARRAY( cpcr->PosLookupRecord, count, HB_PosLookupRecord ) )
 
4587
    goto Fail2;
 
4588
 
 
4589
  plr = cpcr->PosLookupRecord;
 
4590
 
 
4591
  if ( ACCESS_Frame( count * 4L ) )
 
4592
    goto Fail1;
 
4593
 
 
4594
  for ( n = 0; n < count; n++ )
 
4595
  {
 
4596
    plr[n].SequenceIndex   = GET_UShort();
 
4597
    plr[n].LookupListIndex = GET_UShort();
 
4598
  }
 
4599
 
 
4600
  FORGET_Frame();
 
4601
 
 
4602
  return FT_Err_Ok;
 
4603
 
 
4604
Fail1:
 
4605
  FREE( plr );
 
4606
 
 
4607
Fail2:
 
4608
  FREE( l );
 
4609
 
 
4610
Fail3:
 
4611
  FREE( i );
 
4612
 
 
4613
Fail4:
 
4614
  FREE( b );
 
4615
  return error;
 
4616
}
 
4617
 
 
4618
 
 
4619
static void  Free_ChainPosClassRule( HB_ChainPosClassRule*  cpcr,
 
4620
                                     FT_Memory               memory )
 
4621
{
 
4622
  FREE( cpcr->PosLookupRecord );
 
4623
  FREE( cpcr->Lookahead );
 
4624
  FREE( cpcr->Input );
 
4625
  FREE( cpcr->Backtrack );
 
4626
}
 
4627
 
 
4628
 
 
4629
/* PosClassSet */
 
4630
 
 
4631
static FT_Error  Load_ChainPosClassSet(
 
4632
                   HB_ChainContextPosFormat2*  ccpf2,
 
4633
                   HB_ChainPosClassSet*        cpcs,
 
4634
                   FT_Stream                    stream )
 
4635
{
 
4636
  FT_Error  error;
 
4637
  FT_Memory memory = stream->memory;
 
4638
 
 
4639
  FT_UShort               n, m, count;
 
4640
  FT_ULong                cur_offset, new_offset, base_offset;
 
4641
 
 
4642
  HB_ChainPosClassRule*  cpcr;
 
4643
 
 
4644
 
 
4645
  base_offset = FILE_Pos();
 
4646
 
 
4647
  if ( ACCESS_Frame( 2L ) )
 
4648
    return error;
 
4649
 
 
4650
  count = cpcs->ChainPosClassRuleCount = GET_UShort();
 
4651
 
 
4652
  FORGET_Frame();
 
4653
 
 
4654
  cpcs->ChainPosClassRule = NULL;
 
4655
 
 
4656
  if ( ALLOC_ARRAY( cpcs->ChainPosClassRule, count,
 
4657
                    HB_ChainPosClassRule ) )
 
4658
    return error;
 
4659
 
 
4660
  cpcr = cpcs->ChainPosClassRule;
 
4661
 
 
4662
  for ( n = 0; n < count; n++ )
 
4663
  {
 
4664
    if ( ACCESS_Frame( 2L ) )
 
4665
      goto Fail;
 
4666
 
 
4667
    new_offset = GET_UShort() + base_offset;
 
4668
 
 
4669
    FORGET_Frame();
 
4670
 
 
4671
    cur_offset = FILE_Pos();
 
4672
    if ( FILE_Seek( new_offset ) ||
 
4673
         ( error = Load_ChainPosClassRule( ccpf2, &cpcr[n],
 
4674
                                           stream ) ) != FT_Err_Ok )
 
4675
      goto Fail;
 
4676
    (void)FILE_Seek( cur_offset );
 
4677
  }
 
4678
 
 
4679
  return FT_Err_Ok;
 
4680
 
 
4681
Fail:
 
4682
  for ( m = 0; m < n; m++ )
 
4683
    Free_ChainPosClassRule( &cpcr[m], memory );
 
4684
 
 
4685
  FREE( cpcr );
 
4686
  return error;
 
4687
}
 
4688
 
 
4689
 
 
4690
static void  Free_ChainPosClassSet( HB_ChainPosClassSet*  cpcs,
 
4691
                                    FT_Memory              memory )
 
4692
{
 
4693
  FT_UShort               n, count;
 
4694
 
 
4695
  HB_ChainPosClassRule*  cpcr;
 
4696
 
 
4697
 
 
4698
  if ( cpcs->ChainPosClassRule )
 
4699
  {
 
4700
    count = cpcs->ChainPosClassRuleCount;
 
4701
    cpcr  = cpcs->ChainPosClassRule;
 
4702
 
 
4703
    for ( n = 0; n < count; n++ )
 
4704
      Free_ChainPosClassRule( &cpcr[n], memory );
 
4705
 
 
4706
    FREE( cpcr );
 
4707
  }
 
4708
}
 
4709
 
 
4710
 
 
4711
static FT_Error GPOS_Load_EmptyOrClassDefinition( HB_ClassDefinition*  cd,
 
4712
                                             FT_UShort             limit,
 
4713
                                             FT_ULong              class_offset,
 
4714
                                             FT_ULong              base_offset,
 
4715
                                             FT_Stream             stream )
 
4716
{
 
4717
  FT_Error error;
 
4718
  FT_ULong               cur_offset;
 
4719
 
 
4720
  cur_offset = FILE_Pos();
 
4721
 
 
4722
  if ( class_offset )
 
4723
    {
 
4724
      if ( !FILE_Seek( class_offset + base_offset ) )
 
4725
        error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream );
 
4726
    }
 
4727
  else
 
4728
     error = _HB_OPEN_Load_EmptyClassDefinition ( cd, stream );
 
4729
 
 
4730
  if (error == FT_Err_Ok)
 
4731
    (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */
 
4732
 
 
4733
  return error;
 
4734
}
 
4735
 
 
4736
/* ChainContextPosFormat2 */
 
4737
 
 
4738
static FT_Error  Load_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2,
 
4739
                                        FT_Stream                    stream )
 
4740
{
 
4741
  FT_Error  error;
 
4742
  FT_Memory memory = stream->memory;
 
4743
 
 
4744
  FT_UShort              n, m, count;
 
4745
  FT_ULong               cur_offset, new_offset, base_offset;
 
4746
  FT_ULong               backtrack_offset, input_offset, lookahead_offset;
 
4747
 
 
4748
  HB_ChainPosClassSet*  cpcs;
 
4749
 
 
4750
 
 
4751
  base_offset = FILE_Pos() - 2;
 
4752
 
 
4753
  if ( ACCESS_Frame( 2L ) )
 
4754
    return error;
 
4755
 
 
4756
  new_offset = GET_UShort() + base_offset;
 
4757
 
 
4758
  FORGET_Frame();
 
4759
 
 
4760
  cur_offset = FILE_Pos();
 
4761
  if ( FILE_Seek( new_offset ) ||
 
4762
       ( error = _HB_OPEN_Load_Coverage( &ccpf2->Coverage, stream ) ) != FT_Err_Ok )
 
4763
    return error;
 
4764
  (void)FILE_Seek( cur_offset );
 
4765
 
 
4766
  if ( ACCESS_Frame( 8L ) )
 
4767
    goto Fail5;
 
4768
 
 
4769
  backtrack_offset = GET_UShort();
 
4770
  input_offset     = GET_UShort();
 
4771
  lookahead_offset = GET_UShort();
 
4772
 
 
4773
  /* `ChainPosClassSetCount' is the upper limit for input class values,
 
4774
     thus we read it now to make an additional safety check. No limit
 
4775
     is known or needed for the other two class definitions          */
 
4776
 
 
4777
  count = ccpf2->ChainPosClassSetCount = GET_UShort();
 
4778
 
 
4779
  FORGET_Frame();
 
4780
 
 
4781
  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, 65535,
 
4782
                                              backtrack_offset, base_offset,
 
4783
                                              stream ) ) != FT_Err_Ok )
 
4784
    goto Fail5;
 
4785
  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
 
4786
                                              input_offset, base_offset,
 
4787
                                              stream ) ) != FT_Err_Ok )
 
4788
    goto Fail4;
 
4789
  if ( ( error = GPOS_Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, 65535,
 
4790
                                              lookahead_offset, base_offset,
 
4791
                                              stream ) ) != FT_Err_Ok )
 
4792
    goto Fail3;
 
4793
 
 
4794
  ccpf2->ChainPosClassSet   = NULL;
 
4795
  ccpf2->MaxBacktrackLength = 0;
 
4796
  ccpf2->MaxInputLength     = 0;
 
4797
  ccpf2->MaxLookaheadLength = 0;
 
4798
 
 
4799
  if ( ALLOC_ARRAY( ccpf2->ChainPosClassSet, count, HB_ChainPosClassSet ) )
 
4800
    goto Fail2;
 
4801
 
 
4802
  cpcs = ccpf2->ChainPosClassSet;
 
4803
 
 
4804
  for ( n = 0; n < count; n++ )
 
4805
  {
 
4806
    if ( ACCESS_Frame( 2L ) )
 
4807
      goto Fail1;
 
4808
 
 
4809
    new_offset = GET_UShort() + base_offset;
 
4810
 
 
4811
    FORGET_Frame();
 
4812
 
 
4813
    if ( new_offset != base_offset )      /* not a NULL offset */
 
4814
    {
 
4815
      cur_offset = FILE_Pos();
 
4816
      if ( FILE_Seek( new_offset ) ||
 
4817
           ( error = Load_ChainPosClassSet( ccpf2, &cpcs[n],
 
4818
                                            stream ) ) != FT_Err_Ok )
 
4819
        goto Fail1;
 
4820
      (void)FILE_Seek( cur_offset );
 
4821
    }
 
4822
    else
 
4823
    {
 
4824
      /* we create a ChainPosClassSet table with no entries */
 
4825
 
 
4826
      ccpf2->ChainPosClassSet[n].ChainPosClassRuleCount = 0;
 
4827
      ccpf2->ChainPosClassSet[n].ChainPosClassRule      = NULL;
 
4828
    }
 
4829
  }
 
4830
 
 
4831
  return FT_Err_Ok;
 
4832
 
 
4833
Fail1:
 
4834
  for ( m = 0; m < n; m++ )
 
4835
    Free_ChainPosClassSet( &cpcs[m], memory );
 
4836
 
 
4837
  FREE( cpcs );
 
4838
 
 
4839
Fail2:
 
4840
  _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
 
4841
 
 
4842
Fail3:
 
4843
  _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
 
4844
 
 
4845
Fail4:
 
4846
  _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
 
4847
 
 
4848
Fail5:
 
4849
  _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
 
4850
  return error;
 
4851
}
 
4852
 
 
4853
 
 
4854
static void  Free_ChainContextPos2( HB_ChainContextPosFormat2*  ccpf2,
 
4855
                                 FT_Memory                    memory )
 
4856
{
 
4857
  FT_UShort              n, count;
 
4858
 
 
4859
  HB_ChainPosClassSet*  cpcs;
 
4860
 
 
4861
 
 
4862
  if ( ccpf2->ChainPosClassSet )
 
4863
  {
 
4864
    count = ccpf2->ChainPosClassSetCount;
 
4865
    cpcs  = ccpf2->ChainPosClassSet;
 
4866
 
 
4867
    for ( n = 0; n < count; n++ )
 
4868
      Free_ChainPosClassSet( &cpcs[n], memory );
 
4869
 
 
4870
    FREE( cpcs );
 
4871
  }
 
4872
 
 
4873
  _HB_OPEN_Free_ClassDefinition( &ccpf2->LookaheadClassDef, memory );
 
4874
  _HB_OPEN_Free_ClassDefinition( &ccpf2->InputClassDef, memory );
 
4875
  _HB_OPEN_Free_ClassDefinition( &ccpf2->BacktrackClassDef, memory );
 
4876
 
 
4877
  _HB_OPEN_Free_Coverage( &ccpf2->Coverage, memory );
 
4878
}
 
4879
 
 
4880
 
 
4881
/* ChainContextPosFormat3 */
 
4882
 
 
4883
static FT_Error  Load_ChainContextPos3( HB_ChainContextPosFormat3*  ccpf3,
 
4884
                                        FT_Stream                    stream )
 
4885
{
 
4886
  FT_Error  error;
 
4887
  FT_Memory memory = stream->memory;
 
4888
 
 
4889
  FT_UShort             n, nb, ni, nl, m, count;
 
4890
  FT_UShort             backtrack_count, input_count, lookahead_count;
 
4891
  FT_ULong              cur_offset, new_offset, base_offset;
 
4892
 
 
4893
  HB_Coverage*         b;
 
4894
  HB_Coverage*         i;
 
4895
  HB_Coverage*         l;
 
4896
  HB_PosLookupRecord*  plr;
 
4897
 
 
4898
 
 
4899
  base_offset = FILE_Pos() - 2L;
 
4900
 
 
4901
  if ( ACCESS_Frame( 2L ) )
 
4902
    return error;
 
4903
 
 
4904
  ccpf3->BacktrackGlyphCount = GET_UShort();
 
4905
 
 
4906
  FORGET_Frame();
 
4907
 
 
4908
  ccpf3->BacktrackCoverage = NULL;
 
4909
 
 
4910
  backtrack_count = ccpf3->BacktrackGlyphCount;
 
4911
 
 
4912
  if ( ALLOC_ARRAY( ccpf3->BacktrackCoverage, backtrack_count,
 
4913
                    HB_Coverage ) )
 
4914
    return error;
 
4915
 
 
4916
  b = ccpf3->BacktrackCoverage;
 
4917
 
 
4918
  for ( nb = 0; nb < backtrack_count; nb++ )
 
4919
  {
 
4920
    if ( ACCESS_Frame( 2L ) )
 
4921
      goto Fail4;
 
4922
 
 
4923
    new_offset = GET_UShort() + base_offset;
 
4924
 
 
4925
    FORGET_Frame();
 
4926
 
 
4927
    cur_offset = FILE_Pos();
 
4928
    if ( FILE_Seek( new_offset ) ||
 
4929
         ( error = _HB_OPEN_Load_Coverage( &b[nb], stream ) ) != FT_Err_Ok )
 
4930
      goto Fail4;
 
4931
    (void)FILE_Seek( cur_offset );
 
4932
  }
 
4933
 
 
4934
  if ( ACCESS_Frame( 2L ) )
 
4935
    goto Fail4;
 
4936
 
 
4937
  ccpf3->InputGlyphCount = GET_UShort();
 
4938
 
 
4939
  FORGET_Frame();
 
4940
 
 
4941
  ccpf3->InputCoverage = NULL;
 
4942
 
 
4943
  input_count = ccpf3->InputGlyphCount;
 
4944
 
 
4945
  if ( ALLOC_ARRAY( ccpf3->InputCoverage, input_count, HB_Coverage ) )
 
4946
    goto Fail4;
 
4947
 
 
4948
  i = ccpf3->InputCoverage;
 
4949
 
 
4950
  for ( ni = 0; ni < input_count; ni++ )
 
4951
  {
 
4952
    if ( ACCESS_Frame( 2L ) )
 
4953
      goto Fail3;
 
4954
 
 
4955
    new_offset = GET_UShort() + base_offset;
 
4956
 
 
4957
    FORGET_Frame();
 
4958
 
 
4959
    cur_offset = FILE_Pos();
 
4960
    if ( FILE_Seek( new_offset ) ||
 
4961
         ( error = _HB_OPEN_Load_Coverage( &i[ni], stream ) ) != FT_Err_Ok )
 
4962
      goto Fail3;
 
4963
    (void)FILE_Seek( cur_offset );
 
4964
  }
 
4965
 
 
4966
  if ( ACCESS_Frame( 2L ) )
 
4967
    goto Fail3;
 
4968
 
 
4969
  ccpf3->LookaheadGlyphCount = GET_UShort();
 
4970
 
 
4971
  FORGET_Frame();
 
4972
 
 
4973
  ccpf3->LookaheadCoverage = NULL;
 
4974
 
 
4975
  lookahead_count = ccpf3->LookaheadGlyphCount;
 
4976
 
 
4977
  if ( ALLOC_ARRAY( ccpf3->LookaheadCoverage, lookahead_count,
 
4978
                    HB_Coverage ) )
 
4979
    goto Fail3;
 
4980
 
 
4981
  l = ccpf3->LookaheadCoverage;
 
4982
 
 
4983
  for ( nl = 0; nl < lookahead_count; nl++ )
 
4984
  {
 
4985
    if ( ACCESS_Frame( 2L ) )
 
4986
      goto Fail2;
 
4987
 
 
4988
    new_offset = GET_UShort() + base_offset;
 
4989
 
 
4990
    FORGET_Frame();
 
4991
 
 
4992
    cur_offset = FILE_Pos();
 
4993
    if ( FILE_Seek( new_offset ) ||
 
4994
         ( error = _HB_OPEN_Load_Coverage( &l[nl], stream ) ) != FT_Err_Ok )
 
4995
      goto Fail2;
 
4996
    (void)FILE_Seek( cur_offset );
 
4997
  }
 
4998
 
 
4999
  if ( ACCESS_Frame( 2L ) )
 
5000
    goto Fail2;
 
5001
 
 
5002
  ccpf3->PosCount = GET_UShort();
 
5003
 
 
5004
  FORGET_Frame();
 
5005
 
 
5006
  ccpf3->PosLookupRecord = NULL;
 
5007
 
 
5008
  count = ccpf3->PosCount;
 
5009
 
 
5010
  if ( ALLOC_ARRAY( ccpf3->PosLookupRecord, count, HB_PosLookupRecord ) )
 
5011
    goto Fail2;
 
5012
 
 
5013
  plr = ccpf3->PosLookupRecord;
 
5014
 
 
5015
  if ( ACCESS_Frame( count * 4L ) )
 
5016
    goto Fail1;
 
5017
 
 
5018
  for ( n = 0; n < count; n++ )
 
5019
  {
 
5020
    plr[n].SequenceIndex   = GET_UShort();
 
5021
    plr[n].LookupListIndex = GET_UShort();
 
5022
  }
 
5023
 
 
5024
  FORGET_Frame();
 
5025
 
 
5026
  return FT_Err_Ok;
 
5027
 
 
5028
Fail1:
 
5029
  FREE( plr );
 
5030
 
 
5031
Fail2:
 
5032
  for ( m = 0; m < nl; m++ )
 
5033
    _HB_OPEN_Free_Coverage( &l[m], memory );
 
5034
 
 
5035
  FREE( l );
 
5036
 
 
5037
Fail3:
 
5038
  for ( m = 0; m < ni; m++ )
 
5039
    _HB_OPEN_Free_Coverage( &i[m], memory );
 
5040
 
 
5041
  FREE( i );
 
5042
 
 
5043
Fail4:
 
5044
  for ( m = 0; m < nb; m++ )
 
5045
    _HB_OPEN_Free_Coverage( &b[m], memory );
 
5046
 
 
5047
  FREE( b );
 
5048
  return error;
 
5049
}
 
5050
 
 
5051
 
 
5052
static void  Free_ChainContextPos3( HB_ChainContextPosFormat3*  ccpf3,
 
5053
                                 FT_Memory                    memory )
 
5054
{
 
5055
  FT_UShort      n, count;
 
5056
 
 
5057
  HB_Coverage*  c;
 
5058
 
 
5059
 
 
5060
  FREE( ccpf3->PosLookupRecord );
 
5061
 
 
5062
  if ( ccpf3->LookaheadCoverage )
 
5063
  {
 
5064
    count = ccpf3->LookaheadGlyphCount;
 
5065
    c     = ccpf3->LookaheadCoverage;
 
5066
 
 
5067
    for ( n = 0; n < count; n++ )
 
5068
      _HB_OPEN_Free_Coverage( &c[n], memory );
 
5069
 
 
5070
    FREE( c );
 
5071
  }
 
5072
 
 
5073
  if ( ccpf3->InputCoverage )
 
5074
  {
 
5075
    count = ccpf3->InputGlyphCount;
 
5076
    c     = ccpf3->InputCoverage;
 
5077
 
 
5078
    for ( n = 0; n < count; n++ )
 
5079
      _HB_OPEN_Free_Coverage( &c[n], memory );
 
5080
 
 
5081
    FREE( c );
 
5082
  }
 
5083
 
 
5084
  if ( ccpf3->BacktrackCoverage )
 
5085
  {
 
5086
    count = ccpf3->BacktrackGlyphCount;
 
5087
    c     = ccpf3->BacktrackCoverage;
 
5088
 
 
5089
    for ( n = 0; n < count; n++ )
 
5090
      _HB_OPEN_Free_Coverage( &c[n], memory );
 
5091
 
 
5092
    FREE( c );
 
5093
  }
 
5094
}
 
5095
 
 
5096
 
 
5097
/* ChainContextPos */
 
5098
 
 
5099
static FT_Error  Load_ChainContextPos( HB_GPOS_SubTable* st,
 
5100
                                       FT_Stream             stream )
 
5101
{
 
5102
  FT_Error  error;
 
5103
  HB_ChainContextPos*  ccp = &st->chain;
 
5104
 
 
5105
 
 
5106
  if ( ACCESS_Frame( 2L ) )
 
5107
    return error;
 
5108
 
 
5109
  ccp->PosFormat = GET_UShort();
 
5110
 
 
5111
  FORGET_Frame();
 
5112
 
 
5113
  switch ( ccp->PosFormat )
 
5114
  {
 
5115
  case 1:
 
5116
    return Load_ChainContextPos1( &ccp->ccpf.ccpf1, stream );
 
5117
 
 
5118
  case 2:
 
5119
    return Load_ChainContextPos2( &ccp->ccpf.ccpf2, stream );
 
5120
 
 
5121
  case 3:
 
5122
    return Load_ChainContextPos3( &ccp->ccpf.ccpf3, stream );
 
5123
 
 
5124
  default:
 
5125
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
5126
  }
 
5127
 
 
5128
  return FT_Err_Ok;               /* never reached */
 
5129
}
 
5130
 
 
5131
 
 
5132
static void  Free_ChainContextPos( HB_GPOS_SubTable* st,
 
5133
                                   FT_Memory             memory )
 
5134
{
 
5135
  HB_ChainContextPos*  ccp = &st->chain;
 
5136
 
 
5137
  switch ( ccp->PosFormat )
 
5138
  {
 
5139
  case 1:
 
5140
    Free_ChainContextPos1( &ccp->ccpf.ccpf1, memory );
 
5141
    break;
 
5142
 
 
5143
  case 2:
 
5144
    Free_ChainContextPos2( &ccp->ccpf.ccpf2, memory );
 
5145
    break;
 
5146
 
 
5147
  case 3:
 
5148
    Free_ChainContextPos3( &ccp->ccpf.ccpf3, memory );
 
5149
    break;
 
5150
  }
 
5151
}
 
5152
 
 
5153
 
 
5154
static FT_Error  Lookup_ChainContextPos1(
 
5155
                   GPOS_Instance*               gpi,
 
5156
                   HB_ChainContextPosFormat1*  ccpf1,
 
5157
                   HB_Buffer                   buffer,
 
5158
                   FT_UShort                    flags,
 
5159
                   FT_UShort                    context_length,
 
5160
                   int                          nesting_level )
 
5161
{
 
5162
  FT_UShort          index, property;
 
5163
  FT_UShort          i, j, k, num_cpr;
 
5164
  FT_UShort          bgc, igc, lgc;
 
5165
  FT_Error           error;
 
5166
  HB_GPOSHeader*    gpos = gpi->gpos;
 
5167
 
 
5168
  HB_ChainPosRule*  cpr;
 
5169
  HB_ChainPosRule   curr_cpr;
 
5170
  HB_GDEFHeader*    gdef;
 
5171
 
 
5172
 
 
5173
  gdef = gpos->gdef;
 
5174
 
 
5175
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
5176
    return error;
 
5177
 
 
5178
  error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
 
5179
  if ( error )
 
5180
    return error;
 
5181
 
 
5182
  cpr     = ccpf1->ChainPosRuleSet[index].ChainPosRule;
 
5183
  num_cpr = ccpf1->ChainPosRuleSet[index].ChainPosRuleCount;
 
5184
 
 
5185
  for ( k = 0; k < num_cpr; k++ )
 
5186
  {
 
5187
    curr_cpr = cpr[k];
 
5188
    bgc      = curr_cpr.BacktrackGlyphCount;
 
5189
    igc      = curr_cpr.InputGlyphCount;
 
5190
    lgc      = curr_cpr.LookaheadGlyphCount;
 
5191
 
 
5192
    if ( context_length != 0xFFFF && context_length < igc )
 
5193
      goto next_chainposrule;
 
5194
 
 
5195
    /* check whether context is too long; it is a first guess only */
 
5196
 
 
5197
    if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
 
5198
      goto next_chainposrule;
 
5199
 
 
5200
    if ( bgc )
 
5201
    {
 
5202
      /* Since we don't know in advance the number of glyphs to inspect,
 
5203
         we search backwards for matches in the backtrack glyph array    */
 
5204
 
 
5205
      for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
 
5206
      {
 
5207
        while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5208
        {
 
5209
          if ( error && error != HB_Err_Not_Covered )
 
5210
            return error;
 
5211
 
 
5212
          if ( j + 1 == bgc - i )
 
5213
            goto next_chainposrule;
 
5214
          j--;
 
5215
        }
 
5216
 
 
5217
        /* In OpenType 1.3, it is undefined whether the offsets of
 
5218
           backtrack glyphs is in logical order or not.  Version 1.4
 
5219
           will clarify this:
 
5220
 
 
5221
             Logical order -      a  b  c  d  e  f  g  h  i  j
 
5222
                                              i
 
5223
             Input offsets -                  0  1
 
5224
             Backtrack offsets -  3  2  1  0
 
5225
             Lookahead offsets -                    0  1  2  3           */
 
5226
 
 
5227
        if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] )
 
5228
          goto next_chainposrule;
 
5229
      }
 
5230
    }
 
5231
 
 
5232
    /* Start at 1 because [0] is implied */
 
5233
 
 
5234
    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
 
5235
    {
 
5236
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5237
      {
 
5238
        if ( error && error != HB_Err_Not_Covered )
 
5239
          return error;
 
5240
 
 
5241
        if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
 
5242
          goto next_chainposrule;
 
5243
        j++;
 
5244
      }
 
5245
 
 
5246
      if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] )
 
5247
        goto next_chainposrule;
 
5248
    }
 
5249
 
 
5250
    /* we are starting to check for lookahead glyphs right after the
 
5251
       last context glyph                                            */
 
5252
 
 
5253
    for ( i = 0; i < lgc; i++, j++ )
 
5254
    {
 
5255
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5256
      {
 
5257
        if ( error && error != HB_Err_Not_Covered )
 
5258
          return error;
 
5259
 
 
5260
        if ( j + lgc - i == (FT_Long)buffer->in_length )
 
5261
          goto next_chainposrule;
 
5262
        j++;
 
5263
      }
 
5264
 
 
5265
      if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] )
 
5266
        goto next_chainposrule;
 
5267
    }
 
5268
 
 
5269
    return Do_ContextPos( gpi, igc,
 
5270
                          curr_cpr.PosCount,
 
5271
                          curr_cpr.PosLookupRecord,
 
5272
                          buffer,
 
5273
                          nesting_level );
 
5274
 
 
5275
  next_chainposrule:
 
5276
    ;
 
5277
  }
 
5278
 
 
5279
  return HB_Err_Not_Covered;
 
5280
}
 
5281
 
 
5282
 
 
5283
static FT_Error  Lookup_ChainContextPos2(
 
5284
                   GPOS_Instance*               gpi,
 
5285
                   HB_ChainContextPosFormat2*  ccpf2,
 
5286
                   HB_Buffer                   buffer,
 
5287
                   FT_UShort                    flags,
 
5288
                   FT_UShort                    context_length,
 
5289
                   int                          nesting_level )
 
5290
{
 
5291
  FT_UShort              index, property;
 
5292
  FT_Memory              memory = gpi->face->memory;
 
5293
  FT_Error               error;
 
5294
  FT_UShort              i, j, k;
 
5295
  FT_UShort              bgc, igc, lgc;
 
5296
  FT_UShort              known_backtrack_classes,
 
5297
                         known_input_classes,
 
5298
                         known_lookahead_classes;
 
5299
 
 
5300
  FT_UShort*             backtrack_classes;
 
5301
  FT_UShort*             input_classes;
 
5302
  FT_UShort*             lookahead_classes;
 
5303
 
 
5304
  FT_UShort*             bc;
 
5305
  FT_UShort*             ic;
 
5306
  FT_UShort*             lc;
 
5307
  HB_GPOSHeader*        gpos = gpi->gpos;
 
5308
 
 
5309
  HB_ChainPosClassSet*  cpcs;
 
5310
  HB_ChainPosClassRule  cpcr;
 
5311
  HB_GDEFHeader*        gdef;
 
5312
 
 
5313
 
 
5314
  gdef = gpos->gdef;
 
5315
 
 
5316
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
5317
    return error;
 
5318
 
 
5319
  /* Note: The coverage table in format 2 doesn't give an index into
 
5320
           anything.  It just lets us know whether or not we need to
 
5321
           do any lookup at all.                                     */
 
5322
 
 
5323
  error = _HB_OPEN_Coverage_Index( &ccpf2->Coverage, IN_CURGLYPH(), &index );
 
5324
  if ( error )
 
5325
    return error;
 
5326
 
 
5327
  if ( ALLOC_ARRAY( backtrack_classes, ccpf2->MaxBacktrackLength, FT_UShort ) )
 
5328
    return error;
 
5329
  known_backtrack_classes = 0;
 
5330
 
 
5331
  if ( ALLOC_ARRAY( input_classes, ccpf2->MaxInputLength, FT_UShort ) )
 
5332
    goto End3;
 
5333
  known_input_classes = 1;
 
5334
 
 
5335
  if ( ALLOC_ARRAY( lookahead_classes, ccpf2->MaxLookaheadLength, FT_UShort ) )
 
5336
    goto End2;
 
5337
  known_lookahead_classes = 0;
 
5338
 
 
5339
  error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_CURGLYPH(),
 
5340
                     &input_classes[0], NULL );
 
5341
  if ( error && error != HB_Err_Not_Covered )
 
5342
    goto End1;
 
5343
 
 
5344
  cpcs = &ccpf2->ChainPosClassSet[input_classes[0]];
 
5345
  if ( !cpcs )
 
5346
  {
 
5347
    error = HB_Err_Invalid_GPOS_SubTable;
 
5348
    goto End1;
 
5349
  }
 
5350
 
 
5351
  for ( k = 0; k < cpcs->ChainPosClassRuleCount; k++ )
 
5352
  {
 
5353
    cpcr = cpcs->ChainPosClassRule[k];
 
5354
    bgc  = cpcr.BacktrackGlyphCount;
 
5355
    igc  = cpcr.InputGlyphCount;
 
5356
    lgc  = cpcr.LookaheadGlyphCount;
 
5357
 
 
5358
    if ( context_length != 0xFFFF && context_length < igc )
 
5359
      goto next_chainposclassrule;
 
5360
 
 
5361
    /* check whether context is too long; it is a first guess only */
 
5362
 
 
5363
    if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
 
5364
      goto next_chainposclassrule;
 
5365
 
 
5366
    if ( bgc )
 
5367
    {
 
5368
      /* Since we don't know in advance the number of glyphs to inspect,
 
5369
         we search backwards for matches in the backtrack glyph array.
 
5370
         Note that `known_backtrack_classes' starts at index 0.         */
 
5371
 
 
5372
      bc       = cpcr.Backtrack;
 
5373
 
 
5374
      for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
 
5375
      {
 
5376
        while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5377
        {
 
5378
          if ( error && error != HB_Err_Not_Covered )
 
5379
            goto End1;
 
5380
 
 
5381
          if ( j + 1 == bgc - i )
 
5382
            goto next_chainposclassrule;
 
5383
          j++;
 
5384
        }
 
5385
 
 
5386
        if ( i >= known_backtrack_classes )
 
5387
        {
 
5388
          /* Keeps us from having to do this for each rule */
 
5389
 
 
5390
          error = _HB_OPEN_Get_Class( &ccpf2->BacktrackClassDef, IN_GLYPH( j ),
 
5391
                             &backtrack_classes[i], NULL );
 
5392
          if ( error && error != HB_Err_Not_Covered )
 
5393
            goto End1;
 
5394
          known_backtrack_classes = i;
 
5395
        }
 
5396
 
 
5397
        if ( bc[i] != backtrack_classes[i] )
 
5398
          goto next_chainposclassrule;
 
5399
      }
 
5400
    }
 
5401
 
 
5402
    ic       = cpcr.Input;
 
5403
 
 
5404
    /* Start at 1 because [0] is implied */
 
5405
 
 
5406
    for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
 
5407
    {
 
5408
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5409
      {
 
5410
        if ( error && error != HB_Err_Not_Covered )
 
5411
          goto End1;
 
5412
 
 
5413
        if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
 
5414
          goto next_chainposclassrule;
 
5415
        j++;
 
5416
      }
 
5417
 
 
5418
      if ( i >= known_input_classes )
 
5419
      {
 
5420
        error = _HB_OPEN_Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ),
 
5421
                           &input_classes[i], NULL );
 
5422
        if ( error && error != HB_Err_Not_Covered )
 
5423
          goto End1;
 
5424
        known_input_classes = i;
 
5425
      }
 
5426
 
 
5427
      if ( ic[i - 1] != input_classes[i] )
 
5428
        goto next_chainposclassrule;
 
5429
    }
 
5430
 
 
5431
    /* we are starting to check for lookahead glyphs right after the
 
5432
       last context glyph                                            */
 
5433
 
 
5434
    lc       = cpcr.Lookahead;
 
5435
 
 
5436
    for ( i = 0; i < lgc; i++, j++ )
 
5437
    {
 
5438
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5439
      {
 
5440
        if ( error && error != HB_Err_Not_Covered )
 
5441
          goto End1;
 
5442
 
 
5443
        if ( j + lgc - i == (FT_Long)buffer->in_length )
 
5444
          goto next_chainposclassrule;
 
5445
        j++;
 
5446
      }
 
5447
 
 
5448
      if ( i >= known_lookahead_classes )
 
5449
      {
 
5450
        error = _HB_OPEN_Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ),
 
5451
                           &lookahead_classes[i], NULL );
 
5452
        if ( error && error != HB_Err_Not_Covered )
 
5453
          goto End1;
 
5454
        known_lookahead_classes = i;
 
5455
      }
 
5456
 
 
5457
      if ( lc[i] != lookahead_classes[i] )
 
5458
        goto next_chainposclassrule;
 
5459
    }
 
5460
 
 
5461
    error = Do_ContextPos( gpi, igc,
 
5462
                           cpcr.PosCount,
 
5463
                           cpcr.PosLookupRecord,
 
5464
                           buffer,
 
5465
                           nesting_level );
 
5466
    goto End1;
 
5467
 
 
5468
  next_chainposclassrule:
 
5469
    ;
 
5470
  }
 
5471
 
 
5472
  error = HB_Err_Not_Covered;
 
5473
 
 
5474
End1:
 
5475
  FREE( lookahead_classes );
 
5476
 
 
5477
End2:
 
5478
  FREE( input_classes );
 
5479
 
 
5480
End3:
 
5481
  FREE( backtrack_classes );
 
5482
  return error;
 
5483
}
 
5484
 
 
5485
 
 
5486
static FT_Error  Lookup_ChainContextPos3(
 
5487
                   GPOS_Instance*               gpi,
 
5488
                   HB_ChainContextPosFormat3*  ccpf3,
 
5489
                   HB_Buffer                   buffer,
 
5490
                   FT_UShort                    flags,
 
5491
                   FT_UShort                    context_length,
 
5492
                   int                          nesting_level )
 
5493
{
 
5494
  FT_UShort        index, i, j, property;
 
5495
  FT_UShort        bgc, igc, lgc;
 
5496
  FT_Error         error;
 
5497
  HB_GPOSHeader*  gpos = gpi->gpos;
 
5498
 
 
5499
  HB_Coverage*    bc;
 
5500
  HB_Coverage*    ic;
 
5501
  HB_Coverage*    lc;
 
5502
  HB_GDEFHeader*  gdef;
 
5503
 
 
5504
 
 
5505
  gdef = gpos->gdef;
 
5506
 
 
5507
  if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
 
5508
    return error;
 
5509
 
 
5510
  bgc = ccpf3->BacktrackGlyphCount;
 
5511
  igc = ccpf3->InputGlyphCount;
 
5512
  lgc = ccpf3->LookaheadGlyphCount;
 
5513
 
 
5514
  if ( context_length != 0xFFFF && context_length < igc )
 
5515
    return HB_Err_Not_Covered;
 
5516
 
 
5517
  /* check whether context is too long; it is a first guess only */
 
5518
 
 
5519
  if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length )
 
5520
    return HB_Err_Not_Covered;
 
5521
 
 
5522
  if ( bgc )
 
5523
  {
 
5524
    /* Since we don't know in advance the number of glyphs to inspect,
 
5525
       we search backwards for matches in the backtrack glyph array    */
 
5526
 
 
5527
    bc       = ccpf3->BacktrackCoverage;
 
5528
 
 
5529
    for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
 
5530
    {
 
5531
      while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5532
      {
 
5533
        if ( error && error != HB_Err_Not_Covered )
 
5534
          return error;
 
5535
 
 
5536
        if ( j + 1 == bgc - i )
 
5537
          return HB_Err_Not_Covered;
 
5538
        j--;
 
5539
      }
 
5540
 
 
5541
      error = _HB_OPEN_Coverage_Index( &bc[i], IN_GLYPH( j ), &index );
 
5542
      if ( error )
 
5543
        return error;
 
5544
    }
 
5545
  }
 
5546
 
 
5547
  ic       = ccpf3->InputCoverage;
 
5548
 
 
5549
  for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
 
5550
  {
 
5551
    /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
 
5552
    while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5553
    {
 
5554
      if ( error && error != HB_Err_Not_Covered )
 
5555
        return error;
 
5556
 
 
5557
      if ( j + igc - i + lgc == (FT_Long)buffer->in_length )
 
5558
        return HB_Err_Not_Covered;
 
5559
      j++;
 
5560
    }
 
5561
 
 
5562
    error = _HB_OPEN_Coverage_Index( &ic[i], IN_GLYPH( j ), &index );
 
5563
    if ( error )
 
5564
      return error;
 
5565
  }
 
5566
 
 
5567
  /* we are starting to check for lookahead glyphs right after the
 
5568
     last context glyph                                            */
 
5569
 
 
5570
  lc       = ccpf3->LookaheadCoverage;
 
5571
 
 
5572
  for ( i = 0; i < lgc; i++, j++ )
 
5573
  {
 
5574
    while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
 
5575
    {
 
5576
      if ( error && error != HB_Err_Not_Covered )
 
5577
        return error;
 
5578
 
 
5579
      if ( j + lgc - i == (FT_Long)buffer->in_length )
 
5580
        return HB_Err_Not_Covered;
 
5581
      j++;
 
5582
    }
 
5583
 
 
5584
    error = _HB_OPEN_Coverage_Index( &lc[i], IN_GLYPH( j ), &index );
 
5585
    if ( error )
 
5586
      return error;
 
5587
  }
 
5588
 
 
5589
  return Do_ContextPos( gpi, igc,
 
5590
                        ccpf3->PosCount,
 
5591
                        ccpf3->PosLookupRecord,
 
5592
                        buffer,
 
5593
                        nesting_level );
 
5594
}
 
5595
 
 
5596
 
 
5597
static FT_Error  Lookup_ChainContextPos(
 
5598
                   GPOS_Instance*        gpi,
 
5599
                   HB_GPOS_SubTable* st,
 
5600
                   HB_Buffer            buffer,
 
5601
                   FT_UShort             flags,
 
5602
                   FT_UShort             context_length,
 
5603
                   int                   nesting_level )
 
5604
{
 
5605
  HB_ChainContextPos*  ccp = &st->chain;
 
5606
 
 
5607
  switch ( ccp->PosFormat )
 
5608
  {
 
5609
  case 1:
 
5610
    return Lookup_ChainContextPos1( gpi, &ccp->ccpf.ccpf1, buffer,
 
5611
                                    flags, context_length,
 
5612
                                    nesting_level );
 
5613
 
 
5614
  case 2:
 
5615
    return Lookup_ChainContextPos2( gpi, &ccp->ccpf.ccpf2, buffer,
 
5616
                                    flags, context_length,
 
5617
                                    nesting_level );
 
5618
 
 
5619
  case 3:
 
5620
    return Lookup_ChainContextPos3( gpi, &ccp->ccpf.ccpf3, buffer,
 
5621
                                    flags, context_length,
 
5622
                                    nesting_level );
 
5623
 
 
5624
  default:
 
5625
    return HB_Err_Invalid_GPOS_SubTable_Format;
 
5626
  }
 
5627
 
 
5628
  return FT_Err_Ok;               /* never reached */
 
5629
}
 
5630
 
 
5631
 
 
5632
 
 
5633
/***********
 
5634
 * GPOS API
 
5635
 ***********/
 
5636
 
 
5637
 
 
5638
 
 
5639
FT_Error  HB_GPOS_Select_Script( HB_GPOSHeader*  gpos,
 
5640
                                 FT_ULong         script_tag,
 
5641
                                 FT_UShort*       script_index )
 
5642
{
 
5643
  FT_UShort          n;
 
5644
 
 
5645
  HB_ScriptList*    sl;
 
5646
  HB_ScriptRecord*  sr;
 
5647
 
 
5648
 
 
5649
  if ( !gpos || !script_index )
 
5650
    return FT_Err_Invalid_Argument;
 
5651
 
 
5652
  sl = &gpos->ScriptList;
 
5653
  sr = sl->ScriptRecord;
 
5654
 
 
5655
  for ( n = 0; n < sl->ScriptCount; n++ )
 
5656
    if ( script_tag == sr[n].ScriptTag )
 
5657
    {
 
5658
      *script_index = n;
 
5659
 
 
5660
      return FT_Err_Ok;
 
5661
    }
 
5662
 
 
5663
  return HB_Err_Not_Covered;
 
5664
}
 
5665
 
 
5666
 
 
5667
 
 
5668
FT_Error  HB_GPOS_Select_Language( HB_GPOSHeader*  gpos,
 
5669
                                   FT_ULong         language_tag,
 
5670
                                   FT_UShort        script_index,
 
5671
                                   FT_UShort*       language_index,
 
5672
                                   FT_UShort*       req_feature_index )
 
5673
{
 
5674
  FT_UShort           n;
 
5675
 
 
5676
  HB_ScriptList*     sl;
 
5677
  HB_ScriptRecord*   sr;
 
5678
  HB_Script*         s;
 
5679
  HB_LangSysRecord*  lsr;
 
5680
 
 
5681
 
 
5682
  if ( !gpos || !language_index || !req_feature_index )
 
5683
    return FT_Err_Invalid_Argument;
 
5684
 
 
5685
  sl = &gpos->ScriptList;
 
5686
  sr = sl->ScriptRecord;
 
5687
 
 
5688
  if ( script_index >= sl->ScriptCount )
 
5689
    return FT_Err_Invalid_Argument;
 
5690
 
 
5691
  s   = &sr[script_index].Script;
 
5692
  lsr = s->LangSysRecord;
 
5693
 
 
5694
  for ( n = 0; n < s->LangSysCount; n++ )
 
5695
    if ( language_tag == lsr[n].LangSysTag )
 
5696
    {
 
5697
      *language_index = n;
 
5698
      *req_feature_index = lsr[n].LangSys.ReqFeatureIndex;
 
5699
 
 
5700
      return FT_Err_Ok;
 
5701
    }
 
5702
 
 
5703
  return HB_Err_Not_Covered;
 
5704
}
 
5705
 
 
5706
 
 
5707
/* selecting 0xFFFF for language_index asks for the values of the
 
5708
   default language (DefaultLangSys)                              */
 
5709
 
 
5710
 
 
5711
FT_Error  HB_GPOS_Select_Feature( HB_GPOSHeader*  gpos,
 
5712
                                  FT_ULong         feature_tag,
 
5713
                                  FT_UShort        script_index,
 
5714
                                  FT_UShort        language_index,
 
5715
                                  FT_UShort*       feature_index )
 
5716
{
 
5717
  FT_UShort           n;
 
5718
 
 
5719
  HB_ScriptList*     sl;
 
5720
  HB_ScriptRecord*   sr;
 
5721
  HB_Script*         s;
 
5722
  HB_LangSysRecord*  lsr;
 
5723
  HB_LangSys*        ls;
 
5724
  FT_UShort*          fi;
 
5725
 
 
5726
  HB_FeatureList*    fl;
 
5727
  HB_FeatureRecord*  fr;
 
5728
 
 
5729
 
 
5730
  if ( !gpos || !feature_index )
 
5731
    return FT_Err_Invalid_Argument;
 
5732
 
 
5733
  sl = &gpos->ScriptList;
 
5734
  sr = sl->ScriptRecord;
 
5735
 
 
5736
  fl = &gpos->FeatureList;
 
5737
  fr = fl->FeatureRecord;
 
5738
 
 
5739
  if ( script_index >= sl->ScriptCount )
 
5740
    return FT_Err_Invalid_Argument;
 
5741
 
 
5742
  s   = &sr[script_index].Script;
 
5743
  lsr = s->LangSysRecord;
 
5744
 
 
5745
  if ( language_index == 0xFFFF )
 
5746
    ls = &s->DefaultLangSys;
 
5747
  else
 
5748
  {
 
5749
    if ( language_index >= s->LangSysCount )
 
5750
      return FT_Err_Invalid_Argument;
 
5751
 
 
5752
    ls = &lsr[language_index].LangSys;
 
5753
  }
 
5754
 
 
5755
  fi = ls->FeatureIndex;
 
5756
 
 
5757
  for ( n = 0; n < ls->FeatureCount; n++ )
 
5758
  {
 
5759
    if ( fi[n] >= fl->FeatureCount )
 
5760
      return HB_Err_Invalid_GPOS_SubTable_Format;
 
5761
 
 
5762
    if ( feature_tag == fr[fi[n]].FeatureTag )
 
5763
    {
 
5764
      *feature_index = fi[n];
 
5765
 
 
5766
      return FT_Err_Ok;
 
5767
    }
 
5768
  }
 
5769
 
 
5770
  return HB_Err_Not_Covered;
 
5771
}
 
5772
 
 
5773
 
 
5774
/* The next three functions return a null-terminated list */
 
5775
 
 
5776
 
 
5777
FT_Error  HB_GPOS_Query_Scripts( HB_GPOSHeader*  gpos,
 
5778
                                 FT_ULong**       script_tag_list )
 
5779
{
 
5780
  FT_Error           error;
 
5781
  FT_Memory          memory;
 
5782
  FT_UShort          n;
 
5783
  FT_ULong*          stl;
 
5784
 
 
5785
  HB_ScriptList*    sl;
 
5786
  HB_ScriptRecord*  sr;
 
5787
 
 
5788
 
 
5789
  if ( !gpos || !script_tag_list )
 
5790
    return FT_Err_Invalid_Argument;
 
5791
 
 
5792
  memory = gpos->memory;
 
5793
  sl = &gpos->ScriptList;
 
5794
  sr = sl->ScriptRecord;
 
5795
 
 
5796
  if ( ALLOC_ARRAY( stl, sl->ScriptCount + 1, FT_ULong ) )
 
5797
    return error;
 
5798
 
 
5799
  for ( n = 0; n < sl->ScriptCount; n++ )
 
5800
    stl[n] = sr[n].ScriptTag;
 
5801
  stl[n] = 0;
 
5802
 
 
5803
  *script_tag_list = stl;
 
5804
 
 
5805
  return FT_Err_Ok;
 
5806
}
 
5807
 
 
5808
 
 
5809
 
 
5810
FT_Error  HB_GPOS_Query_Languages( HB_GPOSHeader*  gpos,
 
5811
                                   FT_UShort        script_index,
 
5812
                                   FT_ULong**       language_tag_list )
 
5813
{
 
5814
  FT_Error            error;
 
5815
  FT_Memory           memory;
 
5816
  FT_UShort           n;
 
5817
  FT_ULong*           ltl;
 
5818
 
 
5819
  HB_ScriptList*     sl;
 
5820
  HB_ScriptRecord*   sr;
 
5821
  HB_Script*         s;
 
5822
  HB_LangSysRecord*  lsr;
 
5823
 
 
5824
 
 
5825
  if ( !gpos || !language_tag_list )
 
5826
    return FT_Err_Invalid_Argument;
 
5827
 
 
5828
  memory = gpos->memory;
 
5829
  sl = &gpos->ScriptList;
 
5830
  sr = sl->ScriptRecord;
 
5831
 
 
5832
  if ( script_index >= sl->ScriptCount )
 
5833
    return FT_Err_Invalid_Argument;
 
5834
 
 
5835
  s   = &sr[script_index].Script;
 
5836
  lsr = s->LangSysRecord;
 
5837
 
 
5838
  if ( ALLOC_ARRAY( ltl, s->LangSysCount + 1, FT_ULong ) )
 
5839
    return error;
 
5840
 
 
5841
  for ( n = 0; n < s->LangSysCount; n++ )
 
5842
    ltl[n] = lsr[n].LangSysTag;
 
5843
  ltl[n] = 0;
 
5844
 
 
5845
  *language_tag_list = ltl;
 
5846
 
 
5847
  return FT_Err_Ok;
 
5848
}
 
5849
 
 
5850
 
 
5851
/* selecting 0xFFFF for language_index asks for the values of the
 
5852
   default language (DefaultLangSys)                              */
 
5853
 
 
5854
 
 
5855
FT_Error  HB_GPOS_Query_Features( HB_GPOSHeader*  gpos,
 
5856
                                  FT_UShort        script_index,
 
5857
                                  FT_UShort        language_index,
 
5858
                                  FT_ULong**       feature_tag_list )
 
5859
{
 
5860
  FT_UShort           n;
 
5861
  FT_Error            error;
 
5862
  FT_Memory           memory;
 
5863
  FT_ULong*           ftl;
 
5864
 
 
5865
  HB_ScriptList*     sl;
 
5866
  HB_ScriptRecord*   sr;
 
5867
  HB_Script*         s;
 
5868
  HB_LangSysRecord*  lsr;
 
5869
  HB_LangSys*        ls;
 
5870
  FT_UShort*          fi;
 
5871
 
 
5872
  HB_FeatureList*    fl;
 
5873
  HB_FeatureRecord*  fr;
 
5874
 
 
5875
 
 
5876
  if ( !gpos || !feature_tag_list )
 
5877
    return FT_Err_Invalid_Argument;
 
5878
 
 
5879
  memory = gpos->memory;
 
5880
  sl = &gpos->ScriptList;
 
5881
  sr = sl->ScriptRecord;
 
5882
 
 
5883
  fl = &gpos->FeatureList;
 
5884
  fr = fl->FeatureRecord;
 
5885
 
 
5886
  if ( script_index >= sl->ScriptCount )
 
5887
    return FT_Err_Invalid_Argument;
 
5888
 
 
5889
  s   = &sr[script_index].Script;
 
5890
  lsr = s->LangSysRecord;
 
5891
 
 
5892
  if ( language_index == 0xFFFF )
 
5893
    ls = &s->DefaultLangSys;
 
5894
  else
 
5895
  {
 
5896
    if ( language_index >= s->LangSysCount )
 
5897
      return FT_Err_Invalid_Argument;
 
5898
 
 
5899
    ls = &lsr[language_index].LangSys;
 
5900
  }
 
5901
 
 
5902
  fi = ls->FeatureIndex;
 
5903
 
 
5904
  if ( ALLOC_ARRAY( ftl, ls->FeatureCount + 1, FT_ULong ) )
 
5905
    return error;
 
5906
 
 
5907
  for ( n = 0; n < ls->FeatureCount; n++ )
 
5908
  {
 
5909
    if ( fi[n] >= fl->FeatureCount )
 
5910
    {
 
5911
      FREE( ftl );
 
5912
      return HB_Err_Invalid_GPOS_SubTable_Format;
 
5913
    }
 
5914
    ftl[n] = fr[fi[n]].FeatureTag;
 
5915
  }
 
5916
  ftl[n] = 0;
 
5917
 
 
5918
  *feature_tag_list = ftl;
 
5919
 
 
5920
  return FT_Err_Ok;
 
5921
}
 
5922
 
 
5923
 
 
5924
typedef FT_Error  (*Lookup_Pos_Func_Type)  ( GPOS_Instance*    gpi,
 
5925
                                             HB_GPOS_SubTable* st,
 
5926
                                             HB_Buffer        buffer,
 
5927
                                             FT_UShort         flags,
 
5928
                                             FT_UShort         context_length,
 
5929
                                             int               nesting_level );
 
5930
static const Lookup_Pos_Func_Type Lookup_Pos_Call_Table[] = {
 
5931
  Lookup_DefaultPos,
 
5932
  Lookup_SinglePos,             /* HB_GPOS_LOOKUP_SINGLE     1 */
 
5933
  Lookup_PairPos,               /* HB_GPOS_LOOKUP_PAIR       2 */
 
5934
  Lookup_CursivePos,            /* HB_GPOS_LOOKUP_CURSIVE    3 */
 
5935
  Lookup_MarkBasePos,           /* HB_GPOS_LOOKUP_MARKBASE   4 */
 
5936
  Lookup_MarkLigPos,            /* HB_GPOS_LOOKUP_MARKLIG    5 */
 
5937
  Lookup_MarkMarkPos,           /* HB_GPOS_LOOKUP_MARKMARK   6 */
 
5938
  Lookup_ContextPos,            /* HB_GPOS_LOOKUP_CONTEXT    7 */
 
5939
  Lookup_ChainContextPos,       /* HB_GPOS_LOOKUP_CHAIN      8 */
 
5940
  Lookup_DefaultPos,            /* HB_GPOS_LOOKUP_EXTENSION  9 */
 
5941
};
 
5942
 
 
5943
/* Do an individual subtable lookup.  Returns FT_Err_Ok if positioning
 
5944
   has been done, or HB_Err_Not_Covered if not.                        */
 
5945
static FT_Error  GPOS_Do_Glyph_Lookup( GPOS_Instance*    gpi,
 
5946
                                       FT_UShort         lookup_index,
 
5947
                                       HB_Buffer        buffer,
 
5948
                                       FT_UShort         context_length,
 
5949
                                       int               nesting_level )
 
5950
{
 
5951
  FT_Error             error = HB_Err_Not_Covered;
 
5952
  FT_UShort            i, flags, lookup_count;
 
5953
  HB_GPOSHeader*       gpos = gpi->gpos;
 
5954
  HB_Lookup*           lo;
 
5955
  int                  lookup_type;
 
5956
  Lookup_Pos_Func_Type Func;
 
5957
 
 
5958
 
 
5959
  nesting_level++;
 
5960
 
 
5961
  if ( nesting_level > HB_MAX_NESTING_LEVEL )
 
5962
    return HB_Err_Too_Many_Nested_Contexts;
 
5963
 
 
5964
  lookup_count = gpos->LookupList.LookupCount;
 
5965
  if (lookup_index >= lookup_count)
 
5966
    return error;
 
5967
 
 
5968
  lo    = &gpos->LookupList.Lookup[lookup_index];
 
5969
  flags = lo->LookupFlag;
 
5970
  lookup_type = lo->LookupType;
 
5971
  if (lookup_type >= ARRAY_LEN (Lookup_Pos_Call_Table))
 
5972
    lookup_type = 0;
 
5973
  Func = Lookup_Pos_Call_Table[lookup_type];
 
5974
 
 
5975
  for ( i = 0; i < lo->SubTableCount; i++ )
 
5976
  {
 
5977
    error = Func ( gpi,
 
5978
                   &lo->SubTable[i].st.gpos,
 
5979
                   buffer,
 
5980
                   flags, context_length,
 
5981
                   nesting_level );
 
5982
 
 
5983
    /* Check whether we have a successful positioning or an error other
 
5984
       than HB_Err_Not_Covered                                         */
 
5985
 
 
5986
    if ( error != HB_Err_Not_Covered )
 
5987
      return error;
 
5988
  }
 
5989
 
 
5990
  return HB_Err_Not_Covered;
 
5991
}
 
5992
 
 
5993
 
 
5994
static FT_Error  Load_DefaultPos( HB_GPOS_SubTable* st,
 
5995
                                  FT_Stream         stream )
 
5996
{
 
5997
  FT_UNUSED(st);
 
5998
  FT_UNUSED(stream);
 
5999
  return HB_Err_Invalid_GPOS_SubTable_Format;
 
6000
}
 
6001
 
 
6002
typedef FT_Error  (*Load_Pos_Func_Type)( HB_GPOS_SubTable* st,
 
6003
                                         FT_Stream         stream );
 
6004
static const Load_Pos_Func_Type Load_Pos_Call_Table[] = {
 
6005
  Load_DefaultPos,
 
6006
  Load_SinglePos,               /* HB_GPOS_LOOKUP_SINGLE     1 */
 
6007
  Load_PairPos,                 /* HB_GPOS_LOOKUP_PAIR       2 */
 
6008
  Load_CursivePos,              /* HB_GPOS_LOOKUP_CURSIVE    3 */
 
6009
  Load_MarkBasePos,             /* HB_GPOS_LOOKUP_MARKBASE   4 */
 
6010
  Load_MarkLigPos,              /* HB_GPOS_LOOKUP_MARKLIG    5 */
 
6011
  Load_MarkMarkPos,             /* HB_GPOS_LOOKUP_MARKMARK   6 */
 
6012
  Load_ContextPos,              /* HB_GPOS_LOOKUP_CONTEXT    7 */
 
6013
  Load_ChainContextPos,         /* HB_GPOS_LOOKUP_CHAIN      8 */
 
6014
  Load_DefaultPos,              /* HB_GPOS_LOOKUP_EXTENSION  9 */
 
6015
};
 
6016
 
 
6017
FT_Error  _HB_GPOS_Load_SubTable( HB_GPOS_SubTable*  st,
 
6018
                                  FT_Stream     stream,
 
6019
                                  FT_UShort     lookup_type )
 
6020
{
 
6021
  Load_Pos_Func_Type Func;
 
6022
 
 
6023
  if (lookup_type >= ARRAY_LEN (Load_Pos_Call_Table))
 
6024
    lookup_type = 0;
 
6025
 
 
6026
  Func = Load_Pos_Call_Table[lookup_type];
 
6027
 
 
6028
  return Func ( st, stream );
 
6029
}
 
6030
 
 
6031
 
 
6032
static void  Free_DefaultPos( HB_GPOS_SubTable* st,
 
6033
                              FT_Memory         memory )
 
6034
{
 
6035
  FT_UNUSED(st);
 
6036
  FT_UNUSED(memory);
 
6037
}
 
6038
 
 
6039
typedef void (*Free_Pos_Func_Type)( HB_GPOS_SubTable* st,
 
6040
                                    FT_Memory         memory );
 
6041
static const Free_Pos_Func_Type Free_Pos_Call_Table[] = {
 
6042
  Free_DefaultPos,
 
6043
  Free_SinglePos,               /* HB_GPOS_LOOKUP_SINGLE     1 */
 
6044
  Free_PairPos,                 /* HB_GPOS_LOOKUP_PAIR       2 */
 
6045
  Free_CursivePos,              /* HB_GPOS_LOOKUP_CURSIVE    3 */
 
6046
  Free_MarkBasePos,             /* HB_GPOS_LOOKUP_MARKBASE   4 */
 
6047
  Free_MarkLigPos,              /* HB_GPOS_LOOKUP_MARKLIG    5 */
 
6048
  Free_MarkMarkPos,             /* HB_GPOS_LOOKUP_MARKMARK   6 */
 
6049
  Free_ContextPos,              /* HB_GPOS_LOOKUP_CONTEXT    7 */
 
6050
  Free_ChainContextPos,         /* HB_GPOS_LOOKUP_CHAIN      8 */
 
6051
  Free_DefaultPos,              /* HB_GPOS_LOOKUP_EXTENSION  9 */
 
6052
};
 
6053
 
 
6054
void  _HB_GPOS_Free_SubTable( HB_GPOS_SubTable*  st,
 
6055
                              FT_Memory     memory,
 
6056
                              FT_UShort     lookup_type )
 
6057
{
 
6058
  Free_Pos_Func_Type Func;
 
6059
 
 
6060
  if (lookup_type >= ARRAY_LEN (Free_Pos_Call_Table))
 
6061
    lookup_type = 0;
 
6062
 
 
6063
  Func = Free_Pos_Call_Table[lookup_type];
 
6064
 
 
6065
  Func ( st, memory );
 
6066
}
 
6067
 
 
6068
 
 
6069
 
 
6070
/* apply one lookup to the input string object */
 
6071
 
 
6072
static FT_Error  GPOS_Do_String_Lookup( GPOS_Instance*    gpi,
 
6073
                                   FT_UShort         lookup_index,
 
6074
                                   HB_Buffer        buffer )
 
6075
{
 
6076
  FT_Error         error, retError = HB_Err_Not_Covered;
 
6077
  HB_GPOSHeader*  gpos = gpi->gpos;
 
6078
 
 
6079
  FT_UInt*  properties = gpos->LookupList.Properties;
 
6080
 
 
6081
  int       nesting_level = 0;
 
6082
 
 
6083
 
 
6084
  gpi->last  = 0xFFFF;     /* no last valid glyph for cursive pos. */
 
6085
 
 
6086
  buffer->in_pos = 0;
 
6087
 
 
6088
  while ( buffer->in_pos < buffer->in_length )
 
6089
  {
 
6090
    if ( ~IN_PROPERTIES( buffer->in_pos ) & properties[lookup_index] )
 
6091
    {
 
6092
      /* 0xFFFF indicates that we don't have a context length yet. */
 
6093
 
 
6094
      /* Note that the connection between mark and base glyphs hold
 
6095
         exactly one (string) lookup.  For example, it would be possible
 
6096
         that in the first lookup, mark glyph X is attached to base
 
6097
         glyph A, and in the next lookup it is attached to base glyph B.
 
6098
         It is up to the font designer to provide meaningful lookups and
 
6099
         lookup order.                                                   */
 
6100
 
 
6101
      error = GPOS_Do_Glyph_Lookup( gpi, lookup_index, buffer,
 
6102
                                    0xFFFF, nesting_level );
 
6103
      if ( error && error != HB_Err_Not_Covered )
 
6104
        return error;
 
6105
    }
 
6106
    else
 
6107
    {
 
6108
      /* Contrary to properties defined in GDEF, user-defined properties
 
6109
         will always stop a possible cursive positioning.                */
 
6110
      gpi->last = 0xFFFF;
 
6111
 
 
6112
      error = HB_Err_Not_Covered;
 
6113
    }
 
6114
 
 
6115
    if ( error == HB_Err_Not_Covered )
 
6116
      (buffer->in_pos)++;
 
6117
    else
 
6118
      retError = error;
 
6119
  }
 
6120
 
 
6121
  return retError;
 
6122
}
 
6123
 
 
6124
 
 
6125
static FT_Error  Position_CursiveChain ( HB_Buffer     buffer )
 
6126
{
 
6127
  FT_ULong   i, j;
 
6128
  HB_Position positions = buffer->positions;
 
6129
 
 
6130
  /* First handle all left-to-right connections */
 
6131
  for (j = 0; j < buffer->in_length; j--)
 
6132
  {
 
6133
    if (positions[j].cursive_chain > 0)
 
6134
      positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
 
6135
  }
 
6136
 
 
6137
  /* Then handle all right-to-left connections */
 
6138
  for (i = buffer->in_length; i > 0; i--)
 
6139
  {
 
6140
    j = i - 1;
 
6141
 
 
6142
    if (positions[j].cursive_chain < 0)
 
6143
      positions[j].y_pos += positions[j - positions[j].cursive_chain].y_pos;
 
6144
  }
 
6145
 
 
6146
  return FT_Err_Ok;
 
6147
}
 
6148
 
 
6149
 
 
6150
FT_Error  HB_GPOS_Add_Feature( HB_GPOSHeader*  gpos,
 
6151
                               FT_UShort        feature_index,
 
6152
                               FT_UInt          property )
 
6153
{
 
6154
  FT_UShort    i;
 
6155
 
 
6156
  HB_Feature  feature;
 
6157
  FT_UInt*     properties;
 
6158
  FT_UShort*   index;
 
6159
  FT_UShort    lookup_count;
 
6160
 
 
6161
  /* Each feature can only be added once */
 
6162
 
 
6163
  if ( !gpos ||
 
6164
       feature_index >= gpos->FeatureList.FeatureCount ||
 
6165
       gpos->FeatureList.ApplyCount == gpos->FeatureList.FeatureCount )
 
6166
    return FT_Err_Invalid_Argument;
 
6167
 
 
6168
  gpos->FeatureList.ApplyOrder[gpos->FeatureList.ApplyCount++] = feature_index;
 
6169
 
 
6170
  properties = gpos->LookupList.Properties;
 
6171
 
 
6172
  feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
 
6173
  index   = feature.LookupListIndex;
 
6174
  lookup_count = gpos->LookupList.LookupCount;
 
6175
 
 
6176
  for ( i = 0; i < feature.LookupListCount; i++ )
 
6177
  {
 
6178
    FT_UShort lookup_index = index[i];
 
6179
    if (lookup_index < lookup_count)
 
6180
      properties[lookup_index] |= property;
 
6181
  }
 
6182
 
 
6183
  return FT_Err_Ok;
 
6184
}
 
6185
 
 
6186
 
 
6187
 
 
6188
FT_Error  HB_GPOS_Clear_Features( HB_GPOSHeader*  gpos )
 
6189
{
 
6190
  FT_UShort i;
 
6191
 
 
6192
  FT_UInt*  properties;
 
6193
 
 
6194
 
 
6195
  if ( !gpos )
 
6196
    return FT_Err_Invalid_Argument;
 
6197
 
 
6198
  gpos->FeatureList.ApplyCount = 0;
 
6199
 
 
6200
  properties = gpos->LookupList.Properties;
 
6201
 
 
6202
  for ( i = 0; i < gpos->LookupList.LookupCount; i++ )
 
6203
    properties[i] = 0;
 
6204
 
 
6205
  return FT_Err_Ok;
 
6206
}
 
6207
 
 
6208
 
 
6209
 
 
6210
FT_Error  HB_GPOS_Register_Glyph_Function( HB_GPOSHeader*    gpos,
 
6211
                                           HB_GlyphFunction  gfunc )
 
6212
{
 
6213
  if ( !gpos )
 
6214
    return FT_Err_Invalid_Argument;
 
6215
 
 
6216
  gpos->gfunc = gfunc;
 
6217
 
 
6218
  return FT_Err_Ok;
 
6219
}
 
6220
 
 
6221
 
 
6222
 
 
6223
FT_Error  HB_GPOS_Register_MM_Function( HB_GPOSHeader*  gpos,
 
6224
                                        HB_MMFunction   mmfunc,
 
6225
                                        void*            data )
 
6226
{
 
6227
  if ( !gpos )
 
6228
    return FT_Err_Invalid_Argument;
 
6229
 
 
6230
  gpos->mmfunc = mmfunc;
 
6231
  gpos->data   = data;
 
6232
 
 
6233
  return FT_Err_Ok;
 
6234
}
 
6235
 
 
6236
/* If `dvi' is TRUE, glyph contour points for anchor points and device
 
6237
   tables are ignored -- you will get device independent values.         */
 
6238
 
 
6239
 
 
6240
FT_Error  HB_GPOS_Apply_String( FT_Face            face,
 
6241
                                HB_GPOSHeader*    gpos,
 
6242
                                FT_UShort          load_flags,
 
6243
                                HB_Buffer         buffer,
 
6244
                                FT_Bool            dvi,
 
6245
                                FT_Bool            r2l )
 
6246
{
 
6247
  FT_Error       error, retError = HB_Err_Not_Covered;
 
6248
  GPOS_Instance  gpi;
 
6249
  FT_UShort      i, j, feature_index, lookup_count;
 
6250
  HB_Feature    feature;
 
6251
 
 
6252
  if ( !face || !gpos ||
 
6253
       !buffer || buffer->in_length == 0 || buffer->in_pos >= buffer->in_length )
 
6254
    return FT_Err_Invalid_Argument;
 
6255
 
 
6256
  gpi.face       = face;
 
6257
  gpi.gpos       = gpos;
 
6258
  gpi.load_flags = load_flags;
 
6259
  gpi.r2l        = r2l;
 
6260
  gpi.dvi        = dvi;
 
6261
 
 
6262
  lookup_count = gpos->LookupList.LookupCount;
 
6263
 
 
6264
  for ( i = 0; i < gpos->FeatureList.ApplyCount; i++ )
 
6265
  {
 
6266
    /* index of i'th feature */
 
6267
    feature_index = gpos->FeatureList.ApplyOrder[i];
 
6268
    feature = gpos->FeatureList.FeatureRecord[feature_index].Feature;
 
6269
 
 
6270
    for ( j = 0; j < feature.LookupListCount; j++ )
 
6271
    {
 
6272
      FT_UShort lookup_index = feature.LookupListIndex[j];
 
6273
 
 
6274
      /* Skip nonexistant lookups */
 
6275
      if (lookup_index >= lookup_count)
 
6276
       continue;
 
6277
 
 
6278
      error = GPOS_Do_String_Lookup( &gpi, lookup_index, buffer );
 
6279
      if ( error )
 
6280
      {
 
6281
        if ( error != HB_Err_Not_Covered )
 
6282
          return error;
 
6283
      }
 
6284
      else
 
6285
        retError = error;
 
6286
    }
 
6287
  }
 
6288
 
 
6289
  error = Position_CursiveChain ( buffer );
 
6290
  if ( error )
 
6291
    return error;
 
6292
 
 
6293
  return retError;
 
6294
}
 
6295
 
 
6296
/* END */