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

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/pfr/pfrload.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
/*  pfrload.c                                                              */
 
4
/*                                                                         */
 
5
/*    FreeType PFR 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 "pfrload.h"
 
20
#include FT_INTERNAL_DEBUG_H
 
21
#include FT_INTERNAL_STREAM_H
 
22
 
 
23
#include "pfrerror.h"
 
24
 
 
25
#undef  FT_COMPONENT
 
26
#define FT_COMPONENT  trace_pfr
 
27
 
 
28
 
 
29
  /*************************************************************************/
 
30
  /*************************************************************************/
 
31
  /*****                                                               *****/
 
32
  /*****                          EXTRA ITEMS                          *****/
 
33
  /*****                                                               *****/
 
34
  /*************************************************************************/
 
35
  /*************************************************************************/
 
36
 
 
37
 
 
38
  FT_LOCAL_DEF( FT_Error )
 
39
  pfr_extra_items_skip( FT_Byte*  *pp,
 
40
                        FT_Byte*   limit )
 
41
  {
 
42
    return pfr_extra_items_parse( pp, limit, NULL, NULL );
 
43
  }
 
44
 
 
45
 
 
46
  FT_LOCAL_DEF( FT_Error )
 
47
  pfr_extra_items_parse( FT_Byte*       *pp,
 
48
                         FT_Byte*        limit,
 
49
                         PFR_ExtraItem   item_list,
 
50
                         FT_Pointer      item_data )
 
51
  {
 
52
    FT_Error  error = 0;
 
53
    FT_Byte*  p     = *pp;
 
54
    FT_UInt   num_items, item_type, item_size;
 
55
 
 
56
 
 
57
    PFR_CHECK( 1 );
 
58
    num_items = PFR_NEXT_BYTE( p );
 
59
 
 
60
    for ( ; num_items > 0; num_items-- )
 
61
    {
 
62
      PFR_CHECK( 2 );
 
63
      item_size = PFR_NEXT_BYTE( p );
 
64
      item_type = PFR_NEXT_BYTE( p );
 
65
 
 
66
      PFR_CHECK( item_size );
 
67
 
 
68
      if ( item_list )
 
69
      {
 
70
        PFR_ExtraItem  extra = item_list;
 
71
 
 
72
 
 
73
        for ( extra = item_list; extra->parser != NULL; extra++ )
 
74
        {
 
75
          if ( extra->type == item_type )
 
76
          {
 
77
            error = extra->parser( p, p + item_size, item_data );
 
78
            if ( error ) goto Exit;
 
79
 
 
80
            break;
 
81
          }
 
82
        }
 
83
      }
 
84
 
 
85
      p += item_size;
 
86
    }
 
87
 
 
88
  Exit:
 
89
    *pp = p;
 
90
    return error;
 
91
 
 
92
  Too_Short:
 
93
    FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
 
94
    error = PFR_Err_Invalid_Table;
 
95
    goto Exit;
 
96
  }
 
97
 
 
98
 
 
99
  /*************************************************************************/
 
100
  /*************************************************************************/
 
101
  /*****                                                               *****/
 
102
  /*****                          PFR HEADER                           *****/
 
103
  /*****                                                               *****/
 
104
  /*************************************************************************/
 
105
  /*************************************************************************/
 
106
 
 
107
   static const FT_Frame_Field  pfr_header_fields[] =
 
108
   {
 
109
#undef  FT_STRUCTURE
 
110
#define FT_STRUCTURE  PFR_HeaderRec
 
111
 
 
112
     FT_FRAME_START( 58 ),
 
113
       FT_FRAME_ULONG ( signature ),
 
114
       FT_FRAME_USHORT( version ),
 
115
       FT_FRAME_USHORT( signature2 ),
 
116
       FT_FRAME_USHORT( header_size ),
 
117
 
 
118
       FT_FRAME_USHORT( log_dir_size ),
 
119
       FT_FRAME_USHORT( log_dir_offset ),
 
120
 
 
121
       FT_FRAME_USHORT( log_font_max_size ),
 
122
       FT_FRAME_UOFF3 ( log_font_section_size ),
 
123
       FT_FRAME_UOFF3 ( log_font_section_offset ),
 
124
 
 
125
       FT_FRAME_USHORT( phy_font_max_size ),
 
126
       FT_FRAME_UOFF3 ( phy_font_section_size ),
 
127
       FT_FRAME_UOFF3 ( phy_font_section_offset ),
 
128
 
 
129
       FT_FRAME_USHORT( gps_max_size ),
 
130
       FT_FRAME_UOFF3 ( gps_section_size ),
 
131
       FT_FRAME_UOFF3 ( gps_section_offset ),
 
132
 
 
133
       FT_FRAME_BYTE  ( max_blue_values ),
 
134
       FT_FRAME_BYTE  ( max_x_orus ),
 
135
       FT_FRAME_BYTE  ( max_y_orus ),
 
136
 
 
137
       FT_FRAME_BYTE  ( phy_font_max_size_high ),
 
138
       FT_FRAME_BYTE  ( color_flags ),
 
139
 
 
140
       FT_FRAME_UOFF3 ( bct_max_size ),
 
141
       FT_FRAME_UOFF3 ( bct_set_max_size ),
 
142
       FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
 
143
 
 
144
       FT_FRAME_USHORT( num_phy_fonts ),
 
145
       FT_FRAME_BYTE  ( max_vert_stem_snap ),
 
146
       FT_FRAME_BYTE  ( max_horz_stem_snap ),
 
147
       FT_FRAME_USHORT( max_chars ),
 
148
     FT_FRAME_END
 
149
   };
 
150
 
 
151
 
 
152
  FT_LOCAL_DEF( FT_Error )
 
153
  pfr_header_load( PFR_Header  header,
 
154
                   FT_Stream   stream )
 
155
  {
 
156
    FT_Error  error;
 
157
 
 
158
 
 
159
    /* read header directly */
 
160
    if ( !FT_STREAM_SEEK( 0 )                                &&
 
161
         !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
 
162
    {
 
163
      /* make a few adjustments to the header */
 
164
      header->phy_font_max_size +=
 
165
        (FT_UInt32)header->phy_font_max_size_high << 16;
 
166
    }
 
167
 
 
168
    return error;
 
169
  }
 
170
 
 
171
 
 
172
  FT_LOCAL_DEF( FT_Bool )
 
173
  pfr_header_check( PFR_Header  header )
 
174
  {
 
175
    FT_Bool  result = 1;
 
176
 
 
177
 
 
178
    /* check signature and header size */
 
179
    if ( header->signature  != 0x50465230L ||   /* "PFR0" */
 
180
         header->version     > 4           ||
 
181
         header->header_size < 58          ||
 
182
         header->signature2 != 0x0d0a      )    /* CR/LF  */
 
183
    {
 
184
      result = 0;
 
185
    }
 
186
    return  result;
 
187
  }
 
188
 
 
189
 
 
190
  /***********************************************************************/
 
191
  /***********************************************************************/
 
192
  /*****                                                             *****/
 
193
  /*****                    PFR LOGICAL FONTS                        *****/
 
194
  /*****                                                             *****/
 
195
  /***********************************************************************/
 
196
  /***********************************************************************/
 
197
 
 
198
 
 
199
  FT_LOCAL_DEF( FT_Error )
 
200
  pfr_log_font_count( FT_Stream  stream,
 
201
                      FT_UInt32  section_offset,
 
202
                      FT_UInt   *acount )
 
203
  {
 
204
    FT_Error  error;
 
205
    FT_UInt   count;
 
206
    FT_UInt   result = 0;
 
207
 
 
208
 
 
209
    if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
 
210
      goto Exit;
 
211
 
 
212
    result = count;
 
213
 
 
214
  Exit:
 
215
    *acount = result;
 
216
    return error;
 
217
  }
 
218
 
 
219
 
 
220
  FT_LOCAL_DEF( FT_Error )
 
221
  pfr_log_font_load( PFR_LogFont  log_font,
 
222
                     FT_Stream    stream,
 
223
                     FT_UInt      idx,
 
224
                     FT_UInt32    section_offset,
 
225
                     FT_Bool      size_increment )
 
226
  {
 
227
    FT_UInt    num_log_fonts;
 
228
    FT_UInt    flags;
 
229
    FT_UInt32  offset;
 
230
    FT_UInt32  size;
 
231
    FT_Error   error;
 
232
 
 
233
 
 
234
    if ( FT_STREAM_SEEK( section_offset ) ||
 
235
         FT_READ_USHORT( num_log_fonts )  )
 
236
      goto Exit;
 
237
 
 
238
    if ( idx >= num_log_fonts )
 
239
      return PFR_Err_Invalid_Argument;
 
240
 
 
241
    if ( FT_STREAM_SKIP( idx * 5 ) ||
 
242
         FT_READ_USHORT( size )    ||
 
243
         FT_READ_UOFF3 ( offset )  )
 
244
      goto Exit;
 
245
 
 
246
    /* save logical font size and offset */
 
247
    log_font->size   = size;
 
248
    log_font->offset = offset;
 
249
 
 
250
    /* now, check the rest of the table before loading it */
 
251
    {
 
252
      FT_Byte*  p;
 
253
      FT_Byte*  limit;
 
254
      FT_UInt   local;
 
255
 
 
256
 
 
257
      if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
 
258
        goto Exit;
 
259
 
 
260
      p     = stream->cursor;
 
261
      limit = p + size;
 
262
 
 
263
      PFR_CHECK(13);
 
264
 
 
265
      log_font->matrix[0] = PFR_NEXT_LONG( p );
 
266
      log_font->matrix[1] = PFR_NEXT_LONG( p );
 
267
      log_font->matrix[2] = PFR_NEXT_LONG( p );
 
268
      log_font->matrix[3] = PFR_NEXT_LONG( p );
 
269
 
 
270
      flags = PFR_NEXT_BYTE( p );
 
271
 
 
272
      local = 0;
 
273
      if ( flags & PFR_LOG_STROKE )
 
274
      {
 
275
        local++;
 
276
        if ( flags & PFR_LOG_2BYTE_STROKE )
 
277
          local++;
 
278
 
 
279
        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
 
280
          local += 3;
 
281
      }
 
282
      if ( flags & PFR_LOG_BOLD )
 
283
      {
 
284
        local++;
 
285
        if ( flags & PFR_LOG_2BYTE_BOLD )
 
286
          local++;
 
287
      }
 
288
 
 
289
      PFR_CHECK( local );
 
290
 
 
291
      if ( flags & PFR_LOG_STROKE )
 
292
      {
 
293
        log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
 
294
                                     ? PFR_NEXT_SHORT( p )
 
295
                                     : PFR_NEXT_BYTE( p );
 
296
 
 
297
        if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
 
298
          log_font->miter_limit = PFR_NEXT_LONG( p );
 
299
      }
 
300
 
 
301
      if ( flags & PFR_LOG_BOLD )
 
302
      {
 
303
        log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
 
304
                                   ? PFR_NEXT_SHORT( p )
 
305
                                   : PFR_NEXT_BYTE( p );
 
306
      }
 
307
 
 
308
      if ( flags & PFR_LOG_EXTRA_ITEMS )
 
309
      {
 
310
        error = pfr_extra_items_skip( &p, limit );
 
311
        if (error) goto Fail;
 
312
      }
 
313
 
 
314
      PFR_CHECK(5);
 
315
      log_font->phys_size   = PFR_NEXT_USHORT( p );
 
316
      log_font->phys_offset = PFR_NEXT_ULONG( p );
 
317
      if ( size_increment )
 
318
      {
 
319
        PFR_CHECK( 1 );
 
320
        log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
 
321
      }
 
322
    }
 
323
 
 
324
  Fail:
 
325
    FT_FRAME_EXIT();
 
326
 
 
327
  Exit:
 
328
    return error;
 
329
 
 
330
  Too_Short:
 
331
    FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
 
332
    error = PFR_Err_Invalid_Table;
 
333
    goto Fail;
 
334
  }
 
335
 
 
336
 
 
337
  /***********************************************************************/
 
338
  /***********************************************************************/
 
339
  /*****                                                             *****/
 
340
  /*****                    PFR PHYSICAL FONTS                       *****/
 
341
  /*****                                                             *****/
 
342
  /***********************************************************************/
 
343
  /***********************************************************************/
 
344
 
 
345
 
 
346
  /* load bitmap strikes lists */
 
347
  FT_CALLBACK_DEF( FT_Error )
 
348
  pfr_extra_item_load_bitmap_info( FT_Byte*     p,
 
349
                                   FT_Byte*     limit,
 
350
                                   PFR_PhyFont  phy_font )
 
351
  {
 
352
    FT_Memory   memory = phy_font->memory;
 
353
    PFR_Strike  strike;
 
354
    FT_UInt     flags0;
 
355
    FT_UInt     n, count, size1;
 
356
    FT_Error    error = 0;
 
357
 
 
358
 
 
359
    PFR_CHECK( 5 );
 
360
 
 
361
    p += 3;  /* skip bctSize */
 
362
    flags0 = PFR_NEXT_BYTE( p );
 
363
    count  = PFR_NEXT_BYTE( p );
 
364
 
 
365
    /* re-allocate when needed */
 
366
    if ( phy_font->num_strikes + count > phy_font->max_strikes )
 
367
    {
 
368
      FT_UInt  new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
 
369
 
 
370
 
 
371
      if ( FT_RENEW_ARRAY( phy_font->strikes,
 
372
                           phy_font->num_strikes,
 
373
                           new_max ) )
 
374
        goto Exit;
 
375
 
 
376
      phy_font->max_strikes = new_max;
 
377
    }
 
378
 
 
379
    size1 = 1 + 1 + 1 + 2 + 2 + 1;
 
380
    if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
 
381
      size1++;
 
382
 
 
383
    if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
 
384
      size1++;
 
385
 
 
386
    if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
 
387
      size1++;
 
388
 
 
389
    if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
 
390
      size1++;
 
391
 
 
392
    if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
 
393
      size1++;
 
394
 
 
395
    strike = phy_font->strikes + phy_font->num_strikes;
 
396
 
 
397
    PFR_CHECK( count * size1 );
 
398
 
 
399
    for ( n = 0; n < count; n++, strike++ )
 
400
    {
 
401
      strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
 
402
                            ? PFR_NEXT_USHORT( p )
 
403
                            : PFR_NEXT_BYTE( p );
 
404
 
 
405
      strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
 
406
                            ? PFR_NEXT_USHORT( p )
 
407
                            : PFR_NEXT_BYTE( p );
 
408
 
 
409
      strike->flags       = PFR_NEXT_BYTE( p );
 
410
 
 
411
      strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
 
412
                            ? PFR_NEXT_ULONG( p )
 
413
                            : PFR_NEXT_USHORT( p );
 
414
 
 
415
      strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
 
416
                            ? PFR_NEXT_ULONG( p )
 
417
                            : PFR_NEXT_USHORT( p );
 
418
 
 
419
      strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
 
420
                            ? PFR_NEXT_USHORT( p )
 
421
                            : PFR_NEXT_BYTE( p );
 
422
    }
 
423
 
 
424
    phy_font->num_strikes += count;
 
425
 
 
426
  Exit:
 
427
    return error;
 
428
 
 
429
  Too_Short:
 
430
    error = PFR_Err_Invalid_Table;
 
431
    FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" ));
 
432
    goto Exit;
 
433
  }
 
434
 
 
435
 
 
436
  /* Load font ID.  This is a so-called "unique" name that is rather
 
437
   * long and descriptive (like "Tiresias ScreenFont v7.51").
 
438
   *
 
439
   * Note that a PFR font's family name is contained in an *undocumented*
 
440
   * string of the "auxiliary data" portion of a physical font record.  This
 
441
   * may also contain the "real" style name!
 
442
   *
 
443
   * If no family name is present, the font ID is used instead for the
 
444
   * family.
 
445
   */
 
446
  FT_CALLBACK_DEF( FT_Error )
 
447
  pfr_extra_item_load_font_id( FT_Byte*     p,
 
448
                               FT_Byte*     limit,
 
449
                               PFR_PhyFont  phy_font )
 
450
  {
 
451
    FT_Error    error  = 0;
 
452
    FT_Memory   memory = phy_font->memory;
 
453
    FT_PtrDist  len    = limit - p;
 
454
 
 
455
 
 
456
    if ( phy_font->font_id != NULL )
 
457
      goto Exit;
 
458
 
 
459
    if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
 
460
      goto Exit;
 
461
 
 
462
    /* copy font ID name, and terminate it for safety */
 
463
    FT_MEM_COPY( phy_font->font_id, p, len );
 
464
    phy_font->font_id[len] = 0;
 
465
 
 
466
  Exit:
 
467
    return error;
 
468
  }
 
469
 
 
470
 
 
471
  /* load stem snap tables */
 
472
  FT_CALLBACK_DEF( FT_Error )
 
473
  pfr_extra_item_load_stem_snaps( FT_Byte*     p,
 
474
                                  FT_Byte*     limit,
 
475
                                  PFR_PhyFont  phy_font )
 
476
  {
 
477
    FT_UInt    count, num_vert, num_horz;
 
478
    FT_Int*    snaps;
 
479
    FT_Error   error  = 0;
 
480
    FT_Memory  memory = phy_font->memory;
 
481
 
 
482
 
 
483
    if ( phy_font->vertical.stem_snaps != NULL )
 
484
      goto Exit;
 
485
 
 
486
    PFR_CHECK( 1 );
 
487
    count = PFR_NEXT_BYTE( p );
 
488
 
 
489
    num_vert = count & 15;
 
490
    num_horz = count >> 4;
 
491
    count    = num_vert + num_horz;
 
492
 
 
493
    PFR_CHECK( count * 2 );
 
494
 
 
495
    if ( FT_NEW_ARRAY( snaps, count ) )
 
496
      goto Exit;
 
497
 
 
498
    phy_font->vertical.stem_snaps = snaps;
 
499
    phy_font->horizontal.stem_snaps = snaps + num_vert;
 
500
 
 
501
    for ( ; count > 0; count--, snaps++ )
 
502
      *snaps = FT_NEXT_SHORT( p );
 
503
 
 
504
  Exit:
 
505
    return error;
 
506
 
 
507
  Too_Short:
 
508
    error = PFR_Err_Invalid_Table;
 
509
    FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" ));
 
510
    goto Exit;
 
511
  }
 
512
 
 
513
 
 
514
 
 
515
  /* load kerning pair data */
 
516
  FT_CALLBACK_DEF( FT_Error )
 
517
  pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
 
518
                                     FT_Byte*     limit,
 
519
                                     PFR_PhyFont  phy_font )
 
520
  {
 
521
    PFR_KernItem  item;
 
522
    FT_Error      error  = 0;
 
523
    FT_Memory     memory = phy_font->memory;
 
524
 
 
525
 
 
526
    FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
 
527
 
 
528
    if ( FT_NEW( item ) )
 
529
      goto Exit;
 
530
 
 
531
    PFR_CHECK( 4 );
 
532
 
 
533
    item->pair_count = PFR_NEXT_BYTE( p );
 
534
    item->base_adj   = PFR_NEXT_SHORT( p );
 
535
    item->flags      = PFR_NEXT_BYTE( p );
 
536
    item->offset     = phy_font->offset + ( p - phy_font->cursor );
 
537
 
 
538
#ifndef PFR_CONFIG_NO_CHECKS
 
539
    item->pair_size = 3;
 
540
 
 
541
    if ( item->flags & PFR_KERN_2BYTE_CHAR )
 
542
      item->pair_size += 2;
 
543
 
 
544
    if ( item->flags & PFR_KERN_2BYTE_ADJ )
 
545
      item->pair_size += 1;
 
546
 
 
547
    PFR_CHECK( item->pair_count * item->pair_size );
 
548
#endif
 
549
 
 
550
    /* load first and last pairs into the item to speed up */
 
551
    /* lookup later...                                     */
 
552
    if ( item->pair_count > 0 )
 
553
    {
 
554
      FT_UInt   char1, char2;
 
555
      FT_Byte*  q;
 
556
 
 
557
 
 
558
      if ( item->flags & PFR_KERN_2BYTE_CHAR )
 
559
      {
 
560
        q     = p;
 
561
        char1 = PFR_NEXT_USHORT( q );
 
562
        char2 = PFR_NEXT_USHORT( q );
 
563
 
 
564
        item->pair1 = PFR_KERN_INDEX( char1, char2 );
 
565
 
 
566
        q = p + item->pair_size * ( item->pair_count - 1 );
 
567
        char1 = PFR_NEXT_USHORT( q );
 
568
        char2 = PFR_NEXT_USHORT( q );
 
569
 
 
570
        item->pair2 = PFR_KERN_INDEX( char1, char2 );
 
571
      }
 
572
      else
 
573
      {
 
574
        q     = p;
 
575
        char1 = PFR_NEXT_BYTE( q );
 
576
        char2 = PFR_NEXT_BYTE( q );
 
577
 
 
578
        item->pair1 = PFR_KERN_INDEX( char1, char2 );
 
579
 
 
580
        q = p + item->pair_size * ( item->pair_count - 1 );
 
581
        char1 = PFR_NEXT_BYTE( q );
 
582
        char2 = PFR_NEXT_BYTE( q );
 
583
 
 
584
        item->pair2 = PFR_KERN_INDEX( char1, char2 );
 
585
      }
 
586
 
 
587
      /* add new item to the current list */
 
588
      item->next                 = NULL;
 
589
      *phy_font->kern_items_tail = item;
 
590
      phy_font->kern_items_tail  = &item->next;
 
591
      phy_font->num_kern_pairs  += item->pair_count;
 
592
    }
 
593
    else
 
594
    {
 
595
      /* empty item! */
 
596
      FT_FREE( item );
 
597
    }
 
598
 
 
599
  Exit:
 
600
    return error;
 
601
 
 
602
  Too_Short:
 
603
    FT_FREE( item );
 
604
 
 
605
    error = PFR_Err_Invalid_Table;
 
606
    FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
 
607
               "invalid kerning pairs table\n" ));
 
608
    goto Exit;
 
609
  }
 
610
 
 
611
 
 
612
 /*
 
613
  *  The kerning data embedded in a PFR font are (charcode,charcode)
 
614
  *  pairs; we need to translate them to (gindex,gindex) and sort
 
615
  *  the resulting array.
 
616
  */
 
617
  static FT_UInt
 
618
  pfr_get_gindex( PFR_Char  chars,
 
619
                  FT_UInt   count,
 
620
                  FT_UInt   charcode )
 
621
  {
 
622
    FT_UInt  min = 0;
 
623
    FT_UInt  max = count;
 
624
 
 
625
 
 
626
    while ( min < max )
 
627
    {
 
628
      FT_UInt   mid = ( min + max ) >> 1;
 
629
      PFR_Char  c   = chars + mid;
 
630
 
 
631
 
 
632
      if ( c->char_code == charcode )
 
633
        return mid + 1;
 
634
 
 
635
      if ( c->char_code < charcode )
 
636
        min = mid + 1;
 
637
      else
 
638
        max = mid;
 
639
    }
 
640
    return 0;
 
641
  }
 
642
 
 
643
 
 
644
  FT_CALLBACK_DEF( int )
 
645
  pfr_compare_kern_pairs( const void*  pair1,
 
646
                          const void*  pair2 )
 
647
  {
 
648
    FT_UInt32  p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 );
 
649
    FT_UInt32  p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 );
 
650
 
 
651
 
 
652
    if ( p1 < p2 )
 
653
      return -1;
 
654
    if ( p1 > p2 )
 
655
      return 1;
 
656
    return 0;
 
657
  }
 
658
 
 
659
 
 
660
  static FT_Error
 
661
  pfr_sort_kerning_pairs( FT_Stream    stream,
 
662
                          PFR_PhyFont  phy_font )
 
663
  {
 
664
    FT_Error      error;
 
665
    FT_Memory     memory = stream->memory;
 
666
    PFR_KernPair  pairs;
 
667
    PFR_KernItem  item;
 
668
    PFR_Char      chars     = phy_font->chars;
 
669
    FT_UInt       num_chars = phy_font->num_chars;
 
670
    FT_UInt       count;
 
671
 
 
672
 
 
673
   /* create kerning pairs array
 
674
    */
 
675
    if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) )
 
676
      goto Exit;
 
677
 
 
678
   /* load all kerning items into the array,
 
679
    * converting character codes into glyph indices
 
680
    */
 
681
    pairs = phy_font->kern_pairs;
 
682
    item  = phy_font->kern_items;
 
683
    count = 0;
 
684
 
 
685
    for ( ; item; item = item->next )
 
686
    {
 
687
      FT_UInt   limit = count + item->pair_count;
 
688
      FT_Byte*  p;
 
689
 
 
690
 
 
691
      if ( limit > phy_font->num_kern_pairs )
 
692
      {
 
693
        error = PFR_Err_Invalid_Table;
 
694
        goto Exit;
 
695
      }
 
696
 
 
697
      if ( FT_STREAM_SEEK( item->offset )                       ||
 
698
           FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
 
699
        goto Exit;
 
700
 
 
701
      p = stream->cursor;
 
702
 
 
703
      for ( ; count < limit; count++ )
 
704
      {
 
705
        PFR_KernPair  pair = pairs + count;
 
706
        FT_UInt       char1, char2;
 
707
        FT_Int        kerning;
 
708
 
 
709
 
 
710
        if ( item->flags & PFR_KERN_2BYTE_CHAR )
 
711
        {
 
712
          char1 = FT_NEXT_USHORT( p );
 
713
          char2 = FT_NEXT_USHORT( p );
 
714
        }
 
715
        else
 
716
        {
 
717
          char1 = FT_NEXT_BYTE( p );
 
718
          char2 = FT_NEXT_BYTE( p );
 
719
        }
 
720
 
 
721
        if ( item->flags & PFR_KERN_2BYTE_ADJ )
 
722
          kerning = item->base_adj + FT_NEXT_SHORT( p );
 
723
        else
 
724
          kerning = item->base_adj + FT_NEXT_CHAR( p );
 
725
 
 
726
        pair->glyph1  = pfr_get_gindex( chars, num_chars, char1 );
 
727
        pair->glyph2  = pfr_get_gindex( chars, num_chars, char2 );
 
728
        pair->kerning = kerning;
 
729
      }
 
730
 
 
731
      FT_FRAME_EXIT();
 
732
    }
 
733
 
 
734
   /* sort the resulting array
 
735
    */
 
736
    ft_qsort( pairs, count,
 
737
              sizeof ( PFR_KernPairRec ),
 
738
              pfr_compare_kern_pairs );
 
739
 
 
740
  Exit:
 
741
    if ( error )
 
742
    {
 
743
     /* disable kerning data in case of error
 
744
      */
 
745
      phy_font->num_kern_pairs = 0;
 
746
    }
 
747
 
 
748
    return error;
 
749
  }
 
750
 
 
751
 
 
752
  static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
 
753
  {
 
754
    { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
 
755
    { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
 
756
    { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
 
757
    { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
 
758
    { 0, NULL }
 
759
  };
 
760
 
 
761
 
 
762
  /* Loads a name from the auxiliary data.  Since this extracts undocumented
 
763
   * strings from the font file, we need to be careful here.
 
764
   */
 
765
  static FT_Error
 
766
  pfr_aux_name_load( FT_Byte*     p,
 
767
                     FT_UInt      len,
 
768
                     FT_Memory    memory,
 
769
                     FT_String*  *astring )
 
770
  {
 
771
    FT_Error    error = 0;
 
772
    FT_String*  result = NULL;
 
773
    FT_UInt     n, ok;
 
774
 
 
775
 
 
776
    if ( len > 0 && p[len - 1] == 0 )
 
777
      len--;
 
778
 
 
779
    /* check that each character is ASCII for making sure not to
 
780
       load garbage
 
781
     */
 
782
    ok = ( len > 0 );
 
783
    for ( n = 0; n < len; n++ )
 
784
      if ( p[n] < 32 || p[n] > 127 )
 
785
      {
 
786
        ok = 0;
 
787
        break;
 
788
      }
 
789
 
 
790
    if ( ok )
 
791
    {
 
792
      if ( FT_ALLOC( result, len + 1 ) )
 
793
        goto Exit;
 
794
 
 
795
      FT_MEM_COPY( result, p, len );
 
796
      result[len] = 0;
 
797
    }
 
798
  Exit:
 
799
    *astring = result;
 
800
    return error;
 
801
  }
 
802
 
 
803
 
 
804
  FT_LOCAL_DEF( void )
 
805
  pfr_phy_font_done( PFR_PhyFont  phy_font,
 
806
                     FT_Memory    memory )
 
807
  {
 
808
    FT_FREE( phy_font->font_id );
 
809
    FT_FREE( phy_font->family_name );
 
810
    FT_FREE( phy_font->style_name );
 
811
 
 
812
    FT_FREE( phy_font->vertical.stem_snaps );
 
813
    phy_font->vertical.num_stem_snaps = 0;
 
814
 
 
815
    phy_font->horizontal.stem_snaps     = NULL;
 
816
    phy_font->horizontal.num_stem_snaps = 0;
 
817
 
 
818
    FT_FREE( phy_font->strikes );
 
819
    phy_font->num_strikes = 0;
 
820
    phy_font->max_strikes = 0;
 
821
 
 
822
    FT_FREE( phy_font->chars );
 
823
    phy_font->num_chars    = 0;
 
824
    phy_font->chars_offset = 0;
 
825
 
 
826
    FT_FREE( phy_font->blue_values );
 
827
    phy_font->num_blue_values = 0;
 
828
 
 
829
    FT_FREE( phy_font->kern_pairs );
 
830
    {
 
831
      PFR_KernItem  item, next;
 
832
 
 
833
 
 
834
      item = phy_font->kern_items;
 
835
      while ( item )
 
836
      {
 
837
        next = item->next;
 
838
        FT_FREE( item );
 
839
        item = next;
 
840
      }
 
841
      phy_font->kern_items      = NULL;
 
842
      phy_font->kern_items_tail = NULL;
 
843
    }
 
844
 
 
845
    phy_font->num_kern_pairs = 0;
 
846
  }
 
847
 
 
848
 
 
849
  FT_LOCAL_DEF( FT_Error )
 
850
  pfr_phy_font_load( PFR_PhyFont  phy_font,
 
851
                     FT_Stream    stream,
 
852
                     FT_UInt32    offset,
 
853
                     FT_UInt32    size )
 
854
  {
 
855
    FT_Error   error;
 
856
    FT_Memory  memory = stream->memory;
 
857
    FT_UInt    flags, num_aux;
 
858
    FT_Byte*   p;
 
859
    FT_Byte*   limit;
 
860
 
 
861
 
 
862
    phy_font->memory = memory;
 
863
    phy_font->offset = offset;
 
864
 
 
865
    phy_font->kern_items      = NULL;
 
866
    phy_font->kern_items_tail = &phy_font->kern_items;
 
867
 
 
868
    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
 
869
      goto Exit;
 
870
 
 
871
    phy_font->cursor = stream->cursor;
 
872
 
 
873
    p     = stream->cursor;
 
874
    limit = p + size;
 
875
 
 
876
    PFR_CHECK( 15 );
 
877
    phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
 
878
    phy_font->outline_resolution = PFR_NEXT_USHORT( p );
 
879
    phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
 
880
    phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
 
881
    phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
 
882
    phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
 
883
    phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
 
884
    phy_font->flags      = flags = PFR_NEXT_BYTE( p );
 
885
 
 
886
    /* get the standard advance for non-proprotional fonts */
 
887
    if ( !(flags & PFR_PHY_PROPORTIONAL) )
 
888
    {
 
889
      PFR_CHECK( 2 );
 
890
      phy_font->standard_advance = PFR_NEXT_SHORT( p );
 
891
    }
 
892
 
 
893
    /* load the extra items when present */
 
894
    if ( flags & PFR_PHY_EXTRA_ITEMS )
 
895
    {
 
896
      error =  pfr_extra_items_parse( &p, limit,
 
897
                                      pfr_phy_font_extra_items, phy_font );
 
898
 
 
899
      if ( error )
 
900
        goto Fail;
 
901
    }
 
902
 
 
903
    /* In certain fonts, the auxiliary bytes contain interesting  */
 
904
    /* information. These are not in the specification but can be */
 
905
    /* guessed by looking at the content of a few PFR0 fonts.     */
 
906
    PFR_CHECK( 3 );
 
907
    num_aux = PFR_NEXT_ULONG( p );
 
908
 
 
909
    if ( num_aux > 0 )
 
910
    {
 
911
      FT_Byte*  q = p;
 
912
      FT_Byte*  q2;
 
913
 
 
914
 
 
915
      PFR_CHECK( num_aux );
 
916
      p += num_aux;
 
917
 
 
918
      while ( num_aux > 0 )
 
919
      {
 
920
        FT_UInt  length, type;
 
921
 
 
922
 
 
923
        if ( q + 4 > p )
 
924
          break;
 
925
 
 
926
        length = PFR_NEXT_USHORT( q );
 
927
        if ( length < 4 || length > num_aux )
 
928
          break;
 
929
 
 
930
        q2   = q + length - 2;
 
931
        type = PFR_NEXT_USHORT( q );
 
932
 
 
933
        switch ( type )
 
934
        {
 
935
        case 1:
 
936
          /* this seems to correspond to the font's family name,
 
937
           * padded to 16-bits with one zero when necessary
 
938
           */
 
939
          error = pfr_aux_name_load( q, length - 4U, memory,
 
940
                                     &phy_font->family_name );
 
941
          if ( error )
 
942
            goto Exit;
 
943
          break;
 
944
 
 
945
        case 2:
 
946
          if ( q + 32 > q2 )
 
947
            break;
 
948
 
 
949
          q += 10;
 
950
          phy_font->ascent  = PFR_NEXT_SHORT( q );
 
951
          phy_font->descent = PFR_NEXT_SHORT( q );
 
952
          phy_font->leading = PFR_NEXT_SHORT( q );
 
953
          q += 16;
 
954
          break;
 
955
 
 
956
        case 3:
 
957
          /* this seems to correspond to the font's style name,
 
958
           * padded to 16-bits with one zero when necessary
 
959
           */
 
960
          error = pfr_aux_name_load( q, length - 4U, memory,
 
961
                                     &phy_font->style_name );
 
962
          if ( error )
 
963
            goto Exit;
 
964
          break;
 
965
 
 
966
        default:
 
967
          ;
 
968
        }
 
969
 
 
970
        q        = q2;
 
971
        num_aux -= length;
 
972
      }
 
973
    }
 
974
 
 
975
    /* read the blue values */
 
976
    {
 
977
      FT_UInt  n, count;
 
978
 
 
979
 
 
980
      PFR_CHECK( 1 );
 
981
      phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
 
982
 
 
983
      PFR_CHECK( count * 2 );
 
984
 
 
985
      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
 
986
        goto Fail;
 
987
 
 
988
      for ( n = 0; n < count; n++ )
 
989
        phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
 
990
    }
 
991
 
 
992
    PFR_CHECK( 8 );
 
993
    phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
 
994
    phy_font->blue_scale = PFR_NEXT_BYTE( p );
 
995
 
 
996
    phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
 
997
    phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
 
998
 
 
999
    /* read the character descriptors */
 
1000
    {
 
1001
      FT_UInt  n, count, Size;
 
1002
 
 
1003
 
 
1004
      phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
 
1005
      phy_font->chars_offset = offset + ( p - stream->cursor );
 
1006
 
 
1007
      if ( FT_NEW_ARRAY( phy_font->chars, count ) )
 
1008
        goto Fail;
 
1009
 
 
1010
      Size = 1 + 1 + 2;
 
1011
      if ( flags & PFR_PHY_2BYTE_CHARCODE )
 
1012
        Size += 1;
 
1013
 
 
1014
      if ( flags & PFR_PHY_PROPORTIONAL )
 
1015
        Size += 2;
 
1016
 
 
1017
      if ( flags & PFR_PHY_ASCII_CODE )
 
1018
        Size += 1;
 
1019
 
 
1020
      if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
 
1021
        Size += 1;
 
1022
 
 
1023
      if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
 
1024
        Size += 1;
 
1025
 
 
1026
      PFR_CHECK( count * Size );
 
1027
 
 
1028
      for ( n = 0; n < count; n++ )
 
1029
      {
 
1030
        PFR_Char  cur = &phy_font->chars[n];
 
1031
 
 
1032
 
 
1033
        cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
 
1034
                         ? PFR_NEXT_USHORT( p )
 
1035
                         : PFR_NEXT_BYTE( p );
 
1036
 
 
1037
        cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
 
1038
                         ? PFR_NEXT_SHORT( p )
 
1039
                         : (FT_Int) phy_font->standard_advance;
 
1040
 
 
1041
#if 0
 
1042
        cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
 
1043
                         ? PFR_NEXT_BYTE( p )
 
1044
                         : 0;
 
1045
#else
 
1046
        if ( flags & PFR_PHY_ASCII_CODE )
 
1047
          p += 1;
 
1048
#endif
 
1049
        cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
 
1050
                         ? PFR_NEXT_USHORT( p )
 
1051
                         : PFR_NEXT_BYTE( p );
 
1052
 
 
1053
        cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
 
1054
                          ? PFR_NEXT_ULONG( p )
 
1055
                          : PFR_NEXT_USHORT( p );
 
1056
      }
 
1057
    }
 
1058
 
 
1059
    /* that's it! */
 
1060
 
 
1061
  Fail:
 
1062
    FT_FRAME_EXIT();
 
1063
 
 
1064
    /* save position of bitmap info */
 
1065
    phy_font->bct_offset = FT_STREAM_POS();
 
1066
    phy_font->cursor     = NULL;
 
1067
 
 
1068
    /* now sort kerning pairs */
 
1069
    error = pfr_sort_kerning_pairs( stream, phy_font );
 
1070
 
 
1071
  Exit:
 
1072
    return error;
 
1073
 
 
1074
  Too_Short:
 
1075
    error = PFR_Err_Invalid_Table;
 
1076
    FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
 
1077
    goto Fail;
 
1078
  }
 
1079
 
 
1080
 
 
1081
/* END */