source: trunk/poppler/freetype-2.1.10/src/pfr/pfrload.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

File size: 28.2 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  pfrload.c                                                              */
4/*                                                                         */
5/*    FreeType PFR loader (body).                                          */
6/*                                                                         */
7/*  Copyright 2002, 2003, 2004, 2005 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#ifndef FT_OPTIMIZE_MEMORY
613
614  /*
615   *  The kerning data embedded in a PFR font are (charcode,charcode)
616   *  pairs; we need to translate them to (gindex,gindex) and sort
617   *  the resulting array.
618   */
619  static FT_UInt
620  pfr_get_gindex( PFR_Char  chars,
621                  FT_UInt   count,
622                  FT_UInt   charcode )
623  {
624    FT_UInt  min = 0;
625    FT_UInt  max = count;
626
627
628    while ( min < max )
629    {
630      FT_UInt   mid = ( min + max ) >> 1;
631      PFR_Char  c   = chars + mid;
632
633
634      if ( c->char_code == charcode )
635        return mid + 1;
636
637      if ( c->char_code < charcode )
638        min = mid + 1;
639      else
640        max = mid;
641    }
642    return 0;
643  }
644
645
646  FT_CALLBACK_DEF( int )
647  pfr_compare_kern_pairs( const void*  pair1,
648                          const void*  pair2 )
649  {
650    FT_UInt32  p1 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair1 );
651    FT_UInt32  p2 = PFR_KERN_PAIR_INDEX( (PFR_KernPair)pair2 );
652
653
654    if ( p1 < p2 )
655      return -1;
656    if ( p1 > p2 )
657      return 1;
658    return 0;
659  }
660
661
662  static FT_Error
663  pfr_sort_kerning_pairs( FT_Stream    stream,
664                          PFR_PhyFont  phy_font )
665  {
666    FT_Error      error;
667    FT_Memory     memory = stream->memory;
668    PFR_KernPair  pairs;
669    PFR_KernItem  item;
670    PFR_Char      chars     = phy_font->chars;
671    FT_UInt       num_chars = phy_font->num_chars;
672    FT_UInt       count;
673
674
675    /* create kerning pairs array */
676    if ( FT_NEW_ARRAY( phy_font->kern_pairs, phy_font->num_kern_pairs ) )
677      goto Exit;
678
679    /*
680     *  load all kerning items into the array,
681     *  converting character codes into glyph indices
682     */
683    pairs = phy_font->kern_pairs;
684    item  = phy_font->kern_items;
685    count = 0;
686
687    for ( ; item; item = item->next )
688    {
689      FT_UInt   limit = count + item->pair_count;
690      FT_Byte*  p;
691
692
693      if ( limit > phy_font->num_kern_pairs )
694      {
695        error = PFR_Err_Invalid_Table;
696        goto Exit;
697      }
698
699      if ( FT_STREAM_SEEK( item->offset )                       ||
700           FT_FRAME_ENTER( item->pair_count * item->pair_size ) )
701        goto Exit;
702
703      p = stream->cursor;
704
705      for ( ; count < limit; count++ )
706      {
707        PFR_KernPair  pair = pairs + count;
708        FT_UInt       char1, char2;
709        FT_Int        kerning;
710
711
712        if ( item->flags & PFR_KERN_2BYTE_CHAR )
713        {
714          char1 = FT_NEXT_USHORT( p );
715          char2 = FT_NEXT_USHORT( p );
716        }
717        else
718        {
719          char1 = FT_NEXT_BYTE( p );
720          char2 = FT_NEXT_BYTE( p );
721        }
722
723        if ( item->flags & PFR_KERN_2BYTE_ADJ )
724          kerning = item->base_adj + FT_NEXT_SHORT( p );
725        else
726          kerning = item->base_adj + FT_NEXT_BYTE( p );
727
728        pair->glyph1  = pfr_get_gindex( chars, num_chars, char1 );
729        pair->glyph2  = pfr_get_gindex( chars, num_chars, char2 );
730        pair->kerning = kerning;
731      }
732
733      FT_FRAME_EXIT();
734    }
735
736    /* sort the resulting array */
737    ft_qsort( pairs, count,
738              sizeof ( PFR_KernPairRec ),
739              pfr_compare_kern_pairs );
740
741  Exit:
742    if ( error )
743    {
744     /* disable kerning data in case of error
745      */
746      phy_font->num_kern_pairs = 0;
747    }
748
749    return error;
750  }
751
752#endif /* !FT_OPTIMIZE_MEMORY */
753
754
755  static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
756  {
757    { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
758    { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
759    { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
760    { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
761    { 0, NULL }
762  };
763
764
765  /* Loads a name from the auxiliary data.  Since this extracts undocumented
766   * strings from the font file, we need to be careful here.
767   */
768  static FT_Error
769  pfr_aux_name_load( FT_Byte*     p,
770                     FT_UInt      len,
771                     FT_Memory    memory,
772                     FT_String*  *astring )
773  {
774    FT_Error    error = 0;
775    FT_String*  result = NULL;
776    FT_UInt     n, ok;
777
778
779    if ( len > 0 && p[len - 1] == 0 )
780      len--;
781
782    /* check that each character is ASCII for making sure not to
783       load garbage
784     */
785    ok = ( len > 0 );
786    for ( n = 0; n < len; n++ )
787      if ( p[n] < 32 || p[n] > 127 )
788      {
789        ok = 0;
790        break;
791      }
792
793    if ( ok )
794    {
795      if ( FT_ALLOC( result, len + 1 ) )
796        goto Exit;
797
798      FT_MEM_COPY( result, p, len );
799      result[len] = 0;
800    }
801  Exit:
802    *astring = result;
803    return error;
804  }
805
806
807  FT_LOCAL_DEF( void )
808  pfr_phy_font_done( PFR_PhyFont  phy_font,
809                     FT_Memory    memory )
810  {
811    FT_FREE( phy_font->font_id );
812    FT_FREE( phy_font->family_name );
813    FT_FREE( phy_font->style_name );
814
815    FT_FREE( phy_font->vertical.stem_snaps );
816    phy_font->vertical.num_stem_snaps = 0;
817
818    phy_font->horizontal.stem_snaps     = NULL;
819    phy_font->horizontal.num_stem_snaps = 0;
820
821    FT_FREE( phy_font->strikes );
822    phy_font->num_strikes = 0;
823    phy_font->max_strikes = 0;
824
825    FT_FREE( phy_font->chars );
826    phy_font->num_chars    = 0;
827    phy_font->chars_offset = 0;
828
829    FT_FREE( phy_font->blue_values );
830    phy_font->num_blue_values = 0;
831
832#ifndef FT_OPTIMIZE_MEMORY
833    FT_FREE( phy_font->kern_pairs );
834#endif
835
836    {
837      PFR_KernItem  item, next;
838
839
840      item = phy_font->kern_items;
841      while ( item )
842      {
843        next = item->next;
844        FT_FREE( item );
845        item = next;
846      }
847      phy_font->kern_items      = NULL;
848      phy_font->kern_items_tail = NULL;
849    }
850
851    phy_font->num_kern_pairs = 0;
852  }
853
854
855  FT_LOCAL_DEF( FT_Error )
856  pfr_phy_font_load( PFR_PhyFont  phy_font,
857                     FT_Stream    stream,
858                     FT_UInt32    offset,
859                     FT_UInt32    size )
860  {
861    FT_Error   error;
862    FT_Memory  memory = stream->memory;
863    FT_UInt    flags, num_aux;
864    FT_Byte*   p;
865    FT_Byte*   limit;
866
867
868    phy_font->memory = memory;
869    phy_font->offset = offset;
870
871    phy_font->kern_items      = NULL;
872    phy_font->kern_items_tail = &phy_font->kern_items;
873
874    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
875      goto Exit;
876
877    phy_font->cursor = stream->cursor;
878
879    p     = stream->cursor;
880    limit = p + size;
881
882    PFR_CHECK( 15 );
883    phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
884    phy_font->outline_resolution = PFR_NEXT_USHORT( p );
885    phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
886    phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
887    phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
888    phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
889    phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
890    phy_font->flags      = flags = PFR_NEXT_BYTE( p );
891
892    /* get the standard advance for non-proprotional fonts */
893    if ( !(flags & PFR_PHY_PROPORTIONAL) )
894    {
895      PFR_CHECK( 2 );
896      phy_font->standard_advance = PFR_NEXT_SHORT( p );
897    }
898
899    /* load the extra items when present */
900    if ( flags & PFR_PHY_EXTRA_ITEMS )
901    {
902      error =  pfr_extra_items_parse( &p, limit,
903                                      pfr_phy_font_extra_items, phy_font );
904
905      if ( error )
906        goto Fail;
907    }
908
909    /* In certain fonts, the auxiliary bytes contain interesting  */
910    /* information. These are not in the specification but can be */
911    /* guessed by looking at the content of a few PFR0 fonts.     */
912    PFR_CHECK( 3 );
913    num_aux = PFR_NEXT_ULONG( p );
914
915    if ( num_aux > 0 )
916    {
917      FT_Byte*  q = p;
918      FT_Byte*  q2;
919
920
921      PFR_CHECK( num_aux );
922      p += num_aux;
923
924      while ( num_aux > 0 )
925      {
926        FT_UInt  length, type;
927
928
929        if ( q + 4 > p )
930          break;
931
932        length = PFR_NEXT_USHORT( q );
933        if ( length < 4 || length > num_aux )
934          break;
935
936        q2   = q + length - 2;
937        type = PFR_NEXT_USHORT( q );
938
939        switch ( type )
940        {
941        case 1:
942          /* this seems to correspond to the font's family name,
943           * padded to 16-bits with one zero when necessary
944           */
945          error = pfr_aux_name_load( q, length - 4U, memory,
946                                     &phy_font->family_name );
947          if ( error )
948            goto Exit;
949          break;
950
951        case 2:
952          if ( q + 32 > q2 )
953            break;
954
955          q += 10;
956          phy_font->ascent  = PFR_NEXT_SHORT( q );
957          phy_font->descent = PFR_NEXT_SHORT( q );
958          phy_font->leading = PFR_NEXT_SHORT( q );
959          q += 16;
960          break;
961
962        case 3:
963          /* this seems to correspond to the font's style name,
964           * padded to 16-bits with one zero when necessary
965           */
966          error = pfr_aux_name_load( q, length - 4U, memory,
967                                     &phy_font->style_name );
968          if ( error )
969            goto Exit;
970          break;
971
972        default:
973          ;
974        }
975
976        q        = q2;
977        num_aux -= length;
978      }
979    }
980
981    /* read the blue values */
982    {
983      FT_UInt  n, count;
984
985
986      PFR_CHECK( 1 );
987      phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
988
989      PFR_CHECK( count * 2 );
990
991      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
992        goto Fail;
993
994      for ( n = 0; n < count; n++ )
995        phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
996    }
997
998    PFR_CHECK( 8 );
999    phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
1000    phy_font->blue_scale = PFR_NEXT_BYTE( p );
1001
1002    phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
1003    phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
1004
1005    /* read the character descriptors */
1006    {
1007      FT_UInt  n, count, Size;
1008
1009
1010      phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
1011      phy_font->chars_offset = offset + ( p - stream->cursor );
1012
1013      if ( FT_NEW_ARRAY( phy_font->chars, count ) )
1014        goto Fail;
1015
1016      Size = 1 + 1 + 2;
1017      if ( flags & PFR_PHY_2BYTE_CHARCODE )
1018        Size += 1;
1019
1020      if ( flags & PFR_PHY_PROPORTIONAL )
1021        Size += 2;
1022
1023      if ( flags & PFR_PHY_ASCII_CODE )
1024        Size += 1;
1025
1026      if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
1027        Size += 1;
1028
1029      if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
1030        Size += 1;
1031
1032      PFR_CHECK( count * Size );
1033
1034      for ( n = 0; n < count; n++ )
1035      {
1036        PFR_Char  cur = &phy_font->chars[n];
1037
1038
1039        cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
1040                         ? PFR_NEXT_USHORT( p )
1041                         : PFR_NEXT_BYTE( p );
1042
1043        cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
1044                         ? PFR_NEXT_SHORT( p )
1045                         : (FT_Int) phy_font->standard_advance;
1046
1047#if 0
1048        cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
1049                         ? PFR_NEXT_BYTE( p )
1050                         : 0;
1051#else
1052        if ( flags & PFR_PHY_ASCII_CODE )
1053          p += 1;
1054#endif
1055        cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
1056                         ? PFR_NEXT_USHORT( p )
1057                         : PFR_NEXT_BYTE( p );
1058
1059        cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
1060                          ? PFR_NEXT_ULONG( p )
1061                          : PFR_NEXT_USHORT( p );
1062      }
1063    }
1064
1065    /* that's it! */
1066
1067  Fail:
1068    FT_FRAME_EXIT();
1069
1070    /* save position of bitmap info */
1071    phy_font->bct_offset = FT_STREAM_POS();
1072    phy_font->cursor     = NULL;
1073
1074#ifndef FT_OPTIMIZE_MEMORY
1075    /* now sort kerning pairs */
1076    error = pfr_sort_kerning_pairs( stream, phy_font );
1077#endif
1078
1079  Exit:
1080    return error;
1081
1082  Too_Short:
1083    error = PFR_Err_Invalid_Table;
1084    FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
1085    goto Fail;
1086  }
1087
1088
1089/* END */
Note: See TracBrowser for help on using the repository browser.