~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/pfr/pfrgload.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

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