~ubuntu-branches/ubuntu/utopic/hedgewars/utopic

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/pfr/pfrgload.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2014-01-02 12:37:23 UTC
  • mfrom: (19.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20140102123723-6pdhmyj8tb5y8xbg
Tags: 0.9.20.3-1
New upstream minor release, suitable for unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************/
2
 
/*                                                                         */
3
 
/*  pfrgload.c                                                             */
4
 
/*                                                                         */
5
 
/*    FreeType PFR glyph loader (body).                                    */
6
 
/*                                                                         */
7
 
/*  Copyright 2002, 2003, 2005, 2007, 2010 by                              */
8
 
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9
 
/*                                                                         */
10
 
/*  This file is part of the FreeType project, and may only be used,       */
11
 
/*  modified, and distributed under the terms of the FreeType project      */
12
 
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13
 
/*  this file you indicate that you have read the license and              */
14
 
/*  understand and accept it fully.                                        */
15
 
/*                                                                         */
16
 
/***************************************************************************/
17
 
 
18
 
 
19
 
#include "pfrgload.h"
20
 
#include "pfrsbit.h"
21
 
#include "pfrload.h"            /* for macro definitions */
22
 
#include FT_INTERNAL_DEBUG_H
23
 
 
24
 
#include "pfrerror.h"
25
 
 
26
 
#undef  FT_COMPONENT
27
 
#define FT_COMPONENT  trace_pfr
28
 
 
29
 
 
30
 
  /*************************************************************************/
31
 
  /*************************************************************************/
32
 
  /*****                                                               *****/
33
 
  /*****                      PFR GLYPH BUILDER                        *****/
34
 
  /*****                                                               *****/
35
 
  /*************************************************************************/
36
 
  /*************************************************************************/
37
 
 
38
 
 
39
 
  FT_LOCAL_DEF( void )
40
 
  pfr_glyph_init( PFR_Glyph       glyph,
41
 
                  FT_GlyphLoader  loader )
42
 
  {
43
 
    FT_ZERO( glyph );
44
 
 
45
 
    glyph->loader     = loader;
46
 
    glyph->path_begun = 0;
47
 
 
48
 
    FT_GlyphLoader_Rewind( loader );
49
 
  }
50
 
 
51
 
 
52
 
  FT_LOCAL_DEF( void )
53
 
  pfr_glyph_done( PFR_Glyph  glyph )
54
 
  {
55
 
    FT_Memory  memory = glyph->loader->memory;
56
 
 
57
 
 
58
 
    FT_FREE( glyph->x_control );
59
 
    glyph->y_control = NULL;
60
 
 
61
 
    glyph->max_xy_control = 0;
62
 
#if 0
63
 
    glyph->num_x_control  = 0;
64
 
    glyph->num_y_control  = 0;
65
 
#endif
66
 
 
67
 
    FT_FREE( glyph->subs );
68
 
 
69
 
    glyph->max_subs = 0;
70
 
    glyph->num_subs = 0;
71
 
 
72
 
    glyph->loader     = NULL;
73
 
    glyph->path_begun = 0;
74
 
  }
75
 
 
76
 
 
77
 
  /* close current contour, if any */
78
 
  static void
79
 
  pfr_glyph_close_contour( PFR_Glyph  glyph )
80
 
  {
81
 
    FT_GlyphLoader  loader  = glyph->loader;
82
 
    FT_Outline*     outline = &loader->current.outline;
83
 
    FT_Int          last, first;
84
 
 
85
 
 
86
 
    if ( !glyph->path_begun )
87
 
      return;
88
 
 
89
 
    /* compute first and last point indices in current glyph outline */
90
 
    last  = outline->n_points - 1;
91
 
    first = 0;
92
 
    if ( outline->n_contours > 0 )
93
 
      first = outline->contours[outline->n_contours - 1];
94
 
 
95
 
    /* if the last point falls on the same location than the first one */
96
 
    /* we need to delete it                                            */
97
 
    if ( last > first )
98
 
    {
99
 
      FT_Vector*  p1 = outline->points + first;
100
 
      FT_Vector*  p2 = outline->points + last;
101
 
 
102
 
 
103
 
      if ( p1->x == p2->x && p1->y == p2->y )
104
 
      {
105
 
        outline->n_points--;
106
 
        last--;
107
 
      }
108
 
    }
109
 
 
110
 
    /* don't add empty contours */
111
 
    if ( last >= first )
112
 
      outline->contours[outline->n_contours++] = (short)last;
113
 
 
114
 
    glyph->path_begun = 0;
115
 
  }
116
 
 
117
 
 
118
 
  /* reset glyph to start the loading of a new glyph */
119
 
  static void
120
 
  pfr_glyph_start( PFR_Glyph  glyph )
121
 
  {
122
 
    glyph->path_begun = 0;
123
 
  }
124
 
 
125
 
 
126
 
  static FT_Error
127
 
  pfr_glyph_line_to( PFR_Glyph   glyph,
128
 
                     FT_Vector*  to )
129
 
  {
130
 
    FT_GlyphLoader  loader  = glyph->loader;
131
 
    FT_Outline*     outline = &loader->current.outline;
132
 
    FT_Error        error;
133
 
 
134
 
 
135
 
    /* check that we have begun a new path */
136
 
    if ( !glyph->path_begun )
137
 
    {
138
 
      error = PFR_Err_Invalid_Table;
139
 
      FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
140
 
      goto Exit;
141
 
    }
142
 
 
143
 
    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 0 );
144
 
    if ( !error )
145
 
    {
146
 
      FT_UInt  n = outline->n_points;
147
 
 
148
 
 
149
 
      outline->points[n] = *to;
150
 
      outline->tags  [n] = FT_CURVE_TAG_ON;
151
 
 
152
 
      outline->n_points++;
153
 
    }
154
 
 
155
 
  Exit:
156
 
    return error;
157
 
  }
158
 
 
159
 
 
160
 
  static FT_Error
161
 
  pfr_glyph_curve_to( PFR_Glyph   glyph,
162
 
                      FT_Vector*  control1,
163
 
                      FT_Vector*  control2,
164
 
                      FT_Vector*  to )
165
 
  {
166
 
    FT_GlyphLoader  loader  = glyph->loader;
167
 
    FT_Outline*     outline = &loader->current.outline;
168
 
    FT_Error        error;
169
 
 
170
 
 
171
 
    /* check that we have begun a new path */
172
 
    if ( !glyph->path_begun )
173
 
    {
174
 
      error = PFR_Err_Invalid_Table;
175
 
      FT_ERROR(( "pfr_glyph_line_to: invalid glyph data\n" ));
176
 
      goto Exit;
177
 
    }
178
 
 
179
 
    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
180
 
    if ( !error )
181
 
    {
182
 
      FT_Vector*  vec = outline->points         + outline->n_points;
183
 
      FT_Byte*    tag = (FT_Byte*)outline->tags + outline->n_points;
184
 
 
185
 
 
186
 
      vec[0] = *control1;
187
 
      vec[1] = *control2;
188
 
      vec[2] = *to;
189
 
      tag[0] = FT_CURVE_TAG_CUBIC;
190
 
      tag[1] = FT_CURVE_TAG_CUBIC;
191
 
      tag[2] = FT_CURVE_TAG_ON;
192
 
 
193
 
      outline->n_points = (FT_Short)( outline->n_points + 3 );
194
 
    }
195
 
 
196
 
  Exit:
197
 
    return error;
198
 
  }
199
 
 
200
 
 
201
 
  static FT_Error
202
 
  pfr_glyph_move_to( PFR_Glyph   glyph,
203
 
                     FT_Vector*  to )
204
 
  {
205
 
    FT_GlyphLoader  loader  = glyph->loader;
206
 
    FT_Error        error;
207
 
 
208
 
 
209
 
    /* close current contour if any */
210
 
    pfr_glyph_close_contour( glyph );
211
 
 
212
 
    /* indicate that a new contour has started */
213
 
    glyph->path_begun = 1;
214
 
 
215
 
    /* check that there is space for a new contour and a new point */
216
 
    error = FT_GLYPHLOADER_CHECK_POINTS( loader, 1, 1 );
217
 
    if ( !error )
218
 
      /* add new start point */
219
 
      error = pfr_glyph_line_to( glyph, to );
220
 
 
221
 
    return error;
222
 
  }
223
 
 
224
 
 
225
 
  static void
226
 
  pfr_glyph_end( PFR_Glyph  glyph )
227
 
  {
228
 
    /* close current contour if any */
229
 
    pfr_glyph_close_contour( glyph );
230
 
 
231
 
    /* merge the current glyph into the stack */
232
 
    FT_GlyphLoader_Add( glyph->loader );
233
 
  }
234
 
 
235
 
 
236
 
  /*************************************************************************/
237
 
  /*************************************************************************/
238
 
  /*****                                                               *****/
239
 
  /*****                      PFR GLYPH LOADER                         *****/
240
 
  /*****                                                               *****/
241
 
  /*************************************************************************/
242
 
  /*************************************************************************/
243
 
 
244
 
 
245
 
  /* load a simple glyph */
246
 
  static FT_Error
247
 
  pfr_glyph_load_simple( PFR_Glyph  glyph,
248
 
                         FT_Byte*   p,
249
 
                         FT_Byte*   limit )
250
 
  {
251
 
    FT_Error   error  = PFR_Err_Ok;
252
 
    FT_Memory  memory = glyph->loader->memory;
253
 
    FT_UInt    flags, x_count, y_count, i, count, mask;
254
 
    FT_Int     x;
255
 
 
256
 
 
257
 
    PFR_CHECK( 1 );
258
 
    flags = PFR_NEXT_BYTE( p );
259
 
 
260
 
    /* test for composite glyphs */
261
 
    if ( flags & PFR_GLYPH_IS_COMPOUND )
262
 
      goto Failure;
263
 
 
264
 
    x_count = 0;
265
 
    y_count = 0;
266
 
 
267
 
    if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
268
 
    {
269
 
      PFR_CHECK( 1 );
270
 
      count   = PFR_NEXT_BYTE( p );
271
 
      x_count = count & 15;
272
 
      y_count = count >> 4;
273
 
    }
274
 
    else
275
 
    {
276
 
      if ( flags & PFR_GLYPH_XCOUNT )
277
 
      {
278
 
        PFR_CHECK( 1 );
279
 
        x_count = PFR_NEXT_BYTE( p );
280
 
      }
281
 
 
282
 
      if ( flags & PFR_GLYPH_YCOUNT )
283
 
      {
284
 
        PFR_CHECK( 1 );
285
 
        y_count = PFR_NEXT_BYTE( p );
286
 
      }
287
 
    }
288
 
 
289
 
    count = x_count + y_count;
290
 
 
291
 
    /* re-allocate array when necessary */
292
 
    if ( count > glyph->max_xy_control )
293
 
    {
294
 
      FT_UInt  new_max = FT_PAD_CEIL( count, 8 );
295
 
 
296
 
 
297
 
      if ( FT_RENEW_ARRAY( glyph->x_control,
298
 
                           glyph->max_xy_control,
299
 
                           new_max ) )
300
 
        goto Exit;
301
 
 
302
 
      glyph->max_xy_control = new_max;
303
 
    }
304
 
 
305
 
    glyph->y_control = glyph->x_control + x_count;
306
 
 
307
 
    mask  = 0;
308
 
    x     = 0;
309
 
 
310
 
    for ( i = 0; i < count; i++ )
311
 
    {
312
 
      if ( ( i & 7 ) == 0 )
313
 
      {
314
 
        PFR_CHECK( 1 );
315
 
        mask = PFR_NEXT_BYTE( p );
316
 
      }
317
 
 
318
 
      if ( mask & 1 )
319
 
      {
320
 
        PFR_CHECK( 2 );
321
 
        x = PFR_NEXT_SHORT( p );
322
 
      }
323
 
      else
324
 
      {
325
 
        PFR_CHECK( 1 );
326
 
        x += PFR_NEXT_BYTE( p );
327
 
      }
328
 
 
329
 
      glyph->x_control[i] = x;
330
 
 
331
 
      mask >>= 1;
332
 
    }
333
 
 
334
 
    /* XXX: for now we ignore the secondary stroke and edge definitions */
335
 
    /*      since we don't want to support native PFR hinting           */
336
 
    /*                                                                  */
337
 
    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
338
 
    {
339
 
      error = pfr_extra_items_skip( &p, limit );
340
 
      if ( error )
341
 
        goto Exit;
342
 
    }
343
 
 
344
 
    pfr_glyph_start( glyph );
345
 
 
346
 
    /* now load a simple glyph */
347
 
    {
348
 
      FT_Vector   pos[4];
349
 
      FT_Vector*  cur;
350
 
 
351
 
 
352
 
      pos[0].x = pos[0].y = 0;
353
 
      pos[3]   = pos[0];
354
 
 
355
 
      for (;;)
356
 
      {
357
 
        FT_UInt  format, format_low, args_format = 0, args_count, n;
358
 
 
359
 
 
360
 
        /***************************************************************/
361
 
        /*  read instruction                                           */
362
 
        /*                                                             */
363
 
        PFR_CHECK( 1 );
364
 
        format     = PFR_NEXT_BYTE( p );
365
 
        format_low = format & 15;
366
 
 
367
 
        switch ( format >> 4 )
368
 
        {
369
 
        case 0:                             /* end glyph */
370
 
          FT_TRACE6(( "- end glyph" ));
371
 
          args_count = 0;
372
 
          break;
373
 
 
374
 
        case 1:                             /* general line operation */
375
 
          FT_TRACE6(( "- general line" ));
376
 
          goto Line1;
377
 
 
378
 
        case 4:                             /* move to inside contour  */
379
 
          FT_TRACE6(( "- move to inside" ));
380
 
          goto Line1;
381
 
 
382
 
        case 5:                             /* move to outside contour */
383
 
          FT_TRACE6(( "- move to outside" ));
384
 
        Line1:
385
 
          args_format = format_low;
386
 
          args_count  = 1;
387
 
          break;
388
 
 
389
 
        case 2:                             /* horizontal line to */
390
 
          FT_TRACE6(( "- horizontal line to cx.%d", format_low ));
391
 
          if ( format_low >= x_count )
392
 
            goto Failure;
393
 
          pos[0].x   = glyph->x_control[format_low];
394
 
          pos[0].y   = pos[3].y;
395
 
          pos[3]     = pos[0];
396
 
          args_count = 0;
397
 
          break;
398
 
 
399
 
        case 3:                             /* vertical line to */
400
 
          FT_TRACE6(( "- vertical line to cy.%d", format_low ));
401
 
          if ( format_low >= y_count )
402
 
            goto Failure;
403
 
          pos[0].x   = pos[3].x;
404
 
          pos[0].y   = glyph->y_control[format_low];
405
 
          pos[3]     = pos[0];
406
 
          args_count = 0;
407
 
          break;
408
 
 
409
 
        case 6:                             /* horizontal to vertical curve */
410
 
          FT_TRACE6(( "- hv curve " ));
411
 
          args_format = 0xB8E;
412
 
          args_count  = 3;
413
 
          break;
414
 
 
415
 
        case 7:                             /* vertical to horizontal curve */
416
 
          FT_TRACE6(( "- vh curve" ));
417
 
          args_format = 0xE2B;
418
 
          args_count  = 3;
419
 
          break;
420
 
 
421
 
        default:                            /* general curve to */
422
 
          FT_TRACE6(( "- general curve" ));
423
 
          args_count  = 4;
424
 
          args_format = format_low;
425
 
        }
426
 
 
427
 
        /***********************************************************/
428
 
        /*  now read arguments                                     */
429
 
        /*                                                         */
430
 
        cur = pos;
431
 
        for ( n = 0; n < args_count; n++ )
432
 
        {
433
 
          FT_UInt  idx;
434
 
          FT_Int   delta;
435
 
 
436
 
 
437
 
          /* read the X argument */
438
 
          switch ( args_format & 3 )
439
 
          {
440
 
          case 0:                           /* 8-bit index */
441
 
            PFR_CHECK( 1 );
442
 
            idx  = PFR_NEXT_BYTE( p );
443
 
            if ( idx >= x_count )
444
 
              goto Failure;
445
 
            cur->x = glyph->x_control[idx];
446
 
            FT_TRACE7(( " cx#%d", idx ));
447
 
            break;
448
 
 
449
 
          case 1:                           /* 16-bit value */
450
 
            PFR_CHECK( 2 );
451
 
            cur->x = PFR_NEXT_SHORT( p );
452
 
            FT_TRACE7(( " x.%d", cur->x ));
453
 
            break;
454
 
 
455
 
          case 2:                           /* 8-bit delta */
456
 
            PFR_CHECK( 1 );
457
 
            delta  = PFR_NEXT_INT8( p );
458
 
            cur->x = pos[3].x + delta;
459
 
            FT_TRACE7(( " dx.%d", delta ));
460
 
            break;
461
 
 
462
 
          default:
463
 
            FT_TRACE7(( " |" ));
464
 
            cur->x = pos[3].x;
465
 
          }
466
 
 
467
 
          /* read the Y argument */
468
 
          switch ( ( args_format >> 2 ) & 3 )
469
 
          {
470
 
          case 0:                           /* 8-bit index */
471
 
            PFR_CHECK( 1 );
472
 
            idx  = PFR_NEXT_BYTE( p );
473
 
            if ( idx >= y_count )
474
 
              goto Failure;
475
 
            cur->y = glyph->y_control[idx];
476
 
            FT_TRACE7(( " cy#%d", idx ));
477
 
            break;
478
 
 
479
 
          case 1:                           /* 16-bit absolute value */
480
 
            PFR_CHECK( 2 );
481
 
            cur->y = PFR_NEXT_SHORT( p );
482
 
            FT_TRACE7(( " y.%d", cur->y ));
483
 
            break;
484
 
 
485
 
          case 2:                           /* 8-bit delta */
486
 
            PFR_CHECK( 1 );
487
 
            delta  = PFR_NEXT_INT8( p );
488
 
            cur->y = pos[3].y + delta;
489
 
            FT_TRACE7(( " dy.%d", delta ));
490
 
            break;
491
 
 
492
 
          default:
493
 
            FT_TRACE7(( " -" ));
494
 
            cur->y = pos[3].y;
495
 
          }
496
 
 
497
 
          /* read the additional format flag for the general curve */
498
 
          if ( n == 0 && args_count == 4 )
499
 
          {
500
 
            PFR_CHECK( 1 );
501
 
            args_format = PFR_NEXT_BYTE( p );
502
 
            args_count--;
503
 
          }
504
 
          else
505
 
            args_format >>= 4;
506
 
 
507
 
          /* save the previous point */
508
 
          pos[3] = cur[0];
509
 
          cur++;
510
 
        }
511
 
 
512
 
        FT_TRACE7(( "\n" ));
513
 
 
514
 
        /***********************************************************/
515
 
        /*  finally, execute instruction                           */
516
 
        /*                                                         */
517
 
        switch ( format >> 4 )
518
 
        {
519
 
        case 0:                             /* end glyph => EXIT */
520
 
          pfr_glyph_end( glyph );
521
 
          goto Exit;
522
 
 
523
 
        case 1:                             /* line operations */
524
 
        case 2:
525
 
        case 3:
526
 
          error = pfr_glyph_line_to( glyph, pos );
527
 
          goto Test_Error;
528
 
 
529
 
        case 4:                             /* move to inside contour  */
530
 
        case 5:                             /* move to outside contour */
531
 
          error = pfr_glyph_move_to( glyph, pos );
532
 
          goto Test_Error;
533
 
 
534
 
        default:                            /* curve operations */
535
 
          error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
536
 
 
537
 
        Test_Error:  /* test error condition */
538
 
          if ( error )
539
 
            goto Exit;
540
 
        }
541
 
      } /* for (;;) */
542
 
    }
543
 
 
544
 
  Exit:
545
 
    return error;
546
 
 
547
 
  Failure:
548
 
  Too_Short:
549
 
    error = PFR_Err_Invalid_Table;
550
 
    FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
551
 
    goto Exit;
552
 
  }
553
 
 
554
 
 
555
 
  /* load a composite/compound glyph */
556
 
  static FT_Error
557
 
  pfr_glyph_load_compound( PFR_Glyph  glyph,
558
 
                           FT_Byte*   p,
559
 
                           FT_Byte*   limit )
560
 
  {
561
 
    FT_Error        error  = PFR_Err_Ok;
562
 
    FT_GlyphLoader  loader = glyph->loader;
563
 
    FT_Memory       memory = loader->memory;
564
 
    PFR_SubGlyph    subglyph;
565
 
    FT_UInt         flags, i, count, org_count;
566
 
    FT_Int          x_pos, y_pos;
567
 
 
568
 
 
569
 
    PFR_CHECK( 1 );
570
 
    flags = PFR_NEXT_BYTE( p );
571
 
 
572
 
    /* test for composite glyphs */
573
 
    if ( !( flags & PFR_GLYPH_IS_COMPOUND ) )
574
 
      goto Failure;
575
 
 
576
 
    count = flags & 0x3F;
577
 
 
578
 
    /* ignore extra items when present */
579
 
    /*                                 */
580
 
    if ( flags & PFR_GLYPH_EXTRA_ITEMS )
581
 
    {
582
 
      error = pfr_extra_items_skip( &p, limit );
583
 
      if (error) goto Exit;
584
 
    }
585
 
 
586
 
    /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because   */
587
 
    /* the PFR format is dumb, using direct file offsets to point to the */
588
 
    /* sub-glyphs (instead of glyph indices).  Sigh.                     */
589
 
    /*                                                                   */
590
 
    /* For now, we load the list of sub-glyphs into a different array    */
591
 
    /* but this will prevent us from using the auto-hinter at its best   */
592
 
    /* quality.                                                          */
593
 
    /*                                                                   */
594
 
    org_count = glyph->num_subs;
595
 
 
596
 
    if ( org_count + count > glyph->max_subs )
597
 
    {
598
 
      FT_UInt  new_max = ( org_count + count + 3 ) & (FT_UInt)-4;
599
 
 
600
 
 
601
 
      /* we arbitrarily limit the number of subglyphs */
602
 
      /* to avoid endless recursion                   */
603
 
      if ( new_max > 64 )
604
 
      {
605
 
        error = PFR_Err_Invalid_Table;
606
 
        FT_ERROR(( "pfr_glyph_load_compound:"
607
 
                   " too many compound glyphs components\n" ));
608
 
        goto Exit;
609
 
      }
610
 
 
611
 
      if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
612
 
        goto Exit;
613
 
 
614
 
      glyph->max_subs = new_max;
615
 
    }
616
 
 
617
 
    subglyph = glyph->subs + org_count;
618
 
 
619
 
    for ( i = 0; i < count; i++, subglyph++ )
620
 
    {
621
 
      FT_UInt  format;
622
 
 
623
 
 
624
 
      x_pos = 0;
625
 
      y_pos = 0;
626
 
 
627
 
      PFR_CHECK( 1 );
628
 
      format = PFR_NEXT_BYTE( p );
629
 
 
630
 
      /* read scale when available */
631
 
      subglyph->x_scale = 0x10000L;
632
 
      if ( format & PFR_SUBGLYPH_XSCALE )
633
 
      {
634
 
        PFR_CHECK( 2 );
635
 
        subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
636
 
      }
637
 
 
638
 
      subglyph->y_scale = 0x10000L;
639
 
      if ( format & PFR_SUBGLYPH_YSCALE )
640
 
      {
641
 
        PFR_CHECK( 2 );
642
 
        subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
643
 
      }
644
 
 
645
 
      /* read offset */
646
 
      switch ( format & 3 )
647
 
      {
648
 
      case 1:
649
 
        PFR_CHECK( 2 );
650
 
        x_pos = PFR_NEXT_SHORT( p );
651
 
        break;
652
 
 
653
 
      case 2:
654
 
        PFR_CHECK( 1 );
655
 
        x_pos += PFR_NEXT_INT8( p );
656
 
        break;
657
 
 
658
 
      default:
659
 
        ;
660
 
      }
661
 
 
662
 
      switch ( ( format >> 2 ) & 3 )
663
 
      {
664
 
      case 1:
665
 
        PFR_CHECK( 2 );
666
 
        y_pos = PFR_NEXT_SHORT( p );
667
 
        break;
668
 
 
669
 
      case 2:
670
 
        PFR_CHECK( 1 );
671
 
        y_pos += PFR_NEXT_INT8( p );
672
 
        break;
673
 
 
674
 
      default:
675
 
        ;
676
 
      }
677
 
 
678
 
      subglyph->x_delta = x_pos;
679
 
      subglyph->y_delta = y_pos;
680
 
 
681
 
      /* read glyph position and size now */
682
 
      if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
683
 
      {
684
 
        PFR_CHECK( 2 );
685
 
        subglyph->gps_size = PFR_NEXT_USHORT( p );
686
 
      }
687
 
      else
688
 
      {
689
 
        PFR_CHECK( 1 );
690
 
        subglyph->gps_size = PFR_NEXT_BYTE( p );
691
 
      }
692
 
 
693
 
      if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
694
 
      {
695
 
        PFR_CHECK( 3 );
696
 
        subglyph->gps_offset = PFR_NEXT_LONG( p );
697
 
      }
698
 
      else
699
 
      {
700
 
        PFR_CHECK( 2 );
701
 
        subglyph->gps_offset = PFR_NEXT_USHORT( p );
702
 
      }
703
 
 
704
 
      glyph->num_subs++;
705
 
    }
706
 
 
707
 
  Exit:
708
 
    return error;
709
 
 
710
 
  Failure:
711
 
  Too_Short:
712
 
    error = PFR_Err_Invalid_Table;
713
 
    FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
714
 
    goto Exit;
715
 
  }
716
 
 
717
 
 
718
 
  static FT_Error
719
 
  pfr_glyph_load_rec( PFR_Glyph  glyph,
720
 
                      FT_Stream  stream,
721
 
                      FT_ULong   gps_offset,
722
 
                      FT_ULong   offset,
723
 
                      FT_ULong   size )
724
 
  {
725
 
    FT_Error  error;
726
 
    FT_Byte*  p;
727
 
    FT_Byte*  limit;
728
 
 
729
 
 
730
 
    if ( FT_STREAM_SEEK( gps_offset + offset ) ||
731
 
         FT_FRAME_ENTER( size )                )
732
 
      goto Exit;
733
 
 
734
 
    p     = (FT_Byte*)stream->cursor;
735
 
    limit = p + size;
736
 
 
737
 
    if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
738
 
    {
739
 
      FT_Int          n, old_count, count;
740
 
      FT_GlyphLoader  loader = glyph->loader;
741
 
      FT_Outline*     base   = &loader->base.outline;
742
 
 
743
 
 
744
 
      old_count = glyph->num_subs;
745
 
 
746
 
      /* this is a compound glyph - load it */
747
 
      error = pfr_glyph_load_compound( glyph, p, limit );
748
 
 
749
 
      FT_FRAME_EXIT();
750
 
 
751
 
      if ( error )
752
 
        goto Exit;
753
 
 
754
 
      count = glyph->num_subs - old_count;
755
 
 
756
 
      FT_TRACE4(( "compound glyph with %d elements (offset %lu):\n",
757
 
                  count, offset ));
758
 
 
759
 
      /* now, load each individual glyph */
760
 
      for ( n = 0; n < count; n++ )
761
 
      {
762
 
        FT_Int        i, old_points, num_points;
763
 
        PFR_SubGlyph  subglyph;
764
 
 
765
 
 
766
 
        FT_TRACE4(( "subglyph %d:\n", n ));
767
 
 
768
 
        subglyph   = glyph->subs + old_count + n;
769
 
        old_points = base->n_points;
770
 
 
771
 
        error = pfr_glyph_load_rec( glyph, stream, gps_offset,
772
 
                                    subglyph->gps_offset,
773
 
                                    subglyph->gps_size );
774
 
        if ( error )
775
 
          break;
776
 
 
777
 
        /* note that `glyph->subs' might have been re-allocated */
778
 
        subglyph   = glyph->subs + old_count + n;
779
 
        num_points = base->n_points - old_points;
780
 
 
781
 
        /* translate and eventually scale the new glyph points */
782
 
        if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
783
 
        {
784
 
          FT_Vector*  vec = base->points + old_points;
785
 
 
786
 
 
787
 
          for ( i = 0; i < num_points; i++, vec++ )
788
 
          {
789
 
            vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
790
 
                       subglyph->x_delta;
791
 
            vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
792
 
                       subglyph->y_delta;
793
 
          }
794
 
        }
795
 
        else
796
 
        {
797
 
          FT_Vector*  vec = loader->base.outline.points + old_points;
798
 
 
799
 
 
800
 
          for ( i = 0; i < num_points; i++, vec++ )
801
 
          {
802
 
            vec->x += subglyph->x_delta;
803
 
            vec->y += subglyph->y_delta;
804
 
          }
805
 
        }
806
 
 
807
 
        /* proceed to next sub-glyph */
808
 
      }
809
 
 
810
 
      FT_TRACE4(( "end compound glyph with %d elements\n", count ));
811
 
    }
812
 
    else
813
 
    {
814
 
      FT_TRACE4(( "simple glyph (offset %lu)\n", offset ));
815
 
 
816
 
      /* load a simple glyph */
817
 
      error = pfr_glyph_load_simple( glyph, p, limit );
818
 
 
819
 
      FT_FRAME_EXIT();
820
 
    }
821
 
 
822
 
  Exit:
823
 
    return error;
824
 
  }
825
 
 
826
 
 
827
 
  FT_LOCAL_DEF( FT_Error )
828
 
  pfr_glyph_load( PFR_Glyph  glyph,
829
 
                  FT_Stream  stream,
830
 
                  FT_ULong   gps_offset,
831
 
                  FT_ULong   offset,
832
 
                  FT_ULong   size )
833
 
  {
834
 
    /* initialize glyph loader */
835
 
    FT_GlyphLoader_Rewind( glyph->loader );
836
 
 
837
 
    glyph->num_subs = 0;
838
 
 
839
 
    /* load the glyph, recursively when needed */
840
 
    return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
841
 
  }
842
 
 
843
 
 
844
 
/* END */