xref: /inferno-os/libfreetype/pfrload.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 /***************************************************************************/
2 /*                                                                         */
3 /*  pfrload.c                                                              */
4 /*                                                                         */
5 /*    FreeType PFR loader (body).                                          */
6 /*                                                                         */
7 /*  Copyright 2002 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 )
pfr_extra_items_skip(FT_Byte ** pp,FT_Byte * limit)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 )
pfr_extra_items_parse(FT_Byte ** pp,FT_Byte * limit,PFR_ExtraItem item_list,FT_Pointer item_data)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 )
pfr_header_load(PFR_Header header,FT_Stream stream)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 )
pfr_header_check(PFR_Header header)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 )
pfr_log_font_count(FT_Stream stream,FT_UInt32 section_offset,FT_UInt * acount)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 )
pfr_log_font_load(PFR_LogFont log_font,FT_Stream stream,FT_UInt idx,FT_UInt32 section_offset,FT_Bool size_increment)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 )
pfr_extra_item_load_bitmap_info(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)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 = (phy_font->num_strikes + count + 3) & -4;
369 
370       if ( FT_RENEW_ARRAY( phy_font->strikes,
371                            phy_font->num_strikes,
372                            new_max ) )
373         goto Exit;
374 
375       phy_font->max_strikes = new_max;
376     }
377 
378     size1 = 1 + 1 + 1 + 2 + 2 + 1;
379     if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
380       size1++;
381 
382     if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
383       size1++;
384 
385     if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
386       size1++;
387 
388     if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
389       size1++;
390 
391     if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
392       size1++;
393 
394     strike = phy_font->strikes + phy_font->num_strikes;
395 
396     PFR_CHECK( count * size1 );
397 
398     for ( n = 0; n < count; n++, strike++ )
399     {
400       strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
401                             ? PFR_NEXT_USHORT( p )
402                             : PFR_NEXT_BYTE( p );
403 
404       strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
405                             ? PFR_NEXT_USHORT( p )
406                             : PFR_NEXT_BYTE( p );
407 
408       strike->flags       = PFR_NEXT_BYTE( p );
409 
410       strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
411                             ? PFR_NEXT_ULONG( p )
412                             : PFR_NEXT_USHORT( p );
413 
414       strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
415                             ? PFR_NEXT_ULONG( p )
416                             : PFR_NEXT_USHORT( p );
417 
418       strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
419                             ? PFR_NEXT_USHORT( p )
420                             : PFR_NEXT_BYTE( p );
421     }
422 
423     phy_font->num_strikes += count;
424 
425   Exit:
426     return error;
427 
428   Too_Short:
429     error = PFR_Err_Invalid_Table;
430     FT_ERROR(( "pfr_extra_item_load_bitmap_info: invalid bitmap info table\n" ));
431     goto Exit;
432   }
433 
434 
435   /* load font ID, i.e. name */
436   FT_CALLBACK_DEF( FT_Error )
pfr_extra_item_load_font_id(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)437   pfr_extra_item_load_font_id( FT_Byte*     p,
438                                FT_Byte*     limit,
439                                PFR_PhyFont  phy_font )
440   {
441     FT_Error   error  = 0;
442     FT_Memory  memory = phy_font->memory;
443     FT_UInt    len    = (FT_UInt)( limit - p );
444 
445 
446     if ( phy_font->font_id != NULL )
447       goto Exit;
448 
449     if ( FT_ALLOC( phy_font->font_id, len+1 ) )
450       goto Exit;
451 
452     /* copy font ID name, and terminate it for safety */
453     FT_MEM_COPY( phy_font->font_id, p, len );
454     phy_font->font_id[len] = 0;
455 
456   Exit:
457     return error;
458   }
459 
460 
461   /* load stem snap tables */
462   FT_CALLBACK_DEF( FT_Error )
pfr_extra_item_load_stem_snaps(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)463   pfr_extra_item_load_stem_snaps( FT_Byte*     p,
464                                   FT_Byte*     limit,
465                                   PFR_PhyFont  phy_font )
466   {
467     FT_UInt    count, num_vert, num_horz;
468     FT_Int*    snaps;
469     FT_Error   error  = 0;
470     FT_Memory  memory = phy_font->memory;
471 
472 
473     if ( phy_font->vertical.stem_snaps != NULL )
474       goto Exit;
475 
476     PFR_CHECK( 1 );
477     count = PFR_NEXT_BYTE( p );
478 
479     num_vert = count & 15;
480     num_horz = count >> 4;
481     count    = num_vert + num_horz;
482 
483     PFR_CHECK( count * 2 );
484 
485     if ( FT_NEW_ARRAY( snaps, count ) )
486       goto Exit;
487 
488     phy_font->vertical.stem_snaps = snaps;
489     phy_font->horizontal.stem_snaps = snaps + num_vert;
490 
491     for ( ; count > 0; count--, snaps++ )
492       *snaps = FT_NEXT_SHORT( p );
493 
494   Exit:
495     return error;
496 
497   Too_Short:
498     error = PFR_Err_Invalid_Table;
499     FT_ERROR(( "pfr_exta_item_load_stem_snaps: invalid stem snaps table\n" ));
500     goto Exit;
501   }
502 
503 
504 #if 0
505 
506   /* load kerning pair data */
507   FT_CALLBACK_DEF( FT_Error )
508   pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
509                                      FT_Byte*     limit,
510                                      PFR_PhyFont  phy_font )
511   {
512     FT_Int        count;
513     FT_UShort     base_adj;
514     FT_UInt       flags;
515     FT_UInt       num_pairs;
516     PFR_KernPair  pairs;
517     FT_Error      error  = 0;
518     FT_Memory     memory = phy_font->memory;
519 
520 
521     /* allocate a new kerning item */
522     /* XXX: there may be multiple extra items for kerning */
523     if ( phy_font->kern_pairs != NULL )
524       goto Exit;
525 
526     FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
527 
528     PFR_CHECK( 4 );
529 
530     num_pairs = PFR_NEXT_BYTE( p );
531     base_adj  = PFR_NEXT_SHORT( p );
532     flags     = PFR_NEXT_BYTE( p );
533 
534 #ifndef PFR_CONFIG_NO_CHECKS
535     count = 3;
536 
537     if ( flags & PFR_KERN_2BYTE_CHAR )
538       count += 2;
539 
540     if ( flags & PFR_KERN_2BYTE_ADJ )
541       count += 1;
542 
543     PFR_CHECK( num_pairs * count );
544 #endif
545 
546     if ( FT_NEW_ARRAY( pairs, num_pairs ) )
547       goto Exit;
548 
549     phy_font->num_kern_pairs = num_pairs;
550     phy_font->kern_pairs     = pairs;
551 
552     for (count = num_pairs ; count > 0; count--, pairs++ )
553     {
554       if ( flags & PFR_KERN_2BYTE_CHAR )
555       {
556         pairs->glyph1 = PFR_NEXT_USHORT( p );
557         pairs->glyph2 = PFR_NEXT_USHORT( p );
558       }
559       else
560       {
561         pairs->glyph1 = PFR_NEXT_BYTE( p );
562         pairs->glyph2 = PFR_NEXT_BYTE( p );
563       }
564 
565       if ( flags & PFR_KERN_2BYTE_ADJ )
566         pairs->kerning.x = base_adj + PFR_NEXT_SHORT( p );
567       else
568         pairs->kerning.x = base_adj + PFR_NEXT_INT8( p );
569 
570       pairs->kerning.y = 0;
571 
572       FT_TRACE2(( "kerning %d <-> %d : %ld\n",
573                    pairs->glyph1, pairs->glyph2, pairs->kerning.x ));
574     }
575 
576   Exit:
577     return error;
578 
579   Too_Short:
580     error = PFR_Err_Invalid_Table;
581     FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
582                "invalid kerning pairs table\n" ));
583     goto Exit;
584   }
585 
586 #else /* 0 */
587 
588   /* load kerning pair data */
589   FT_CALLBACK_DEF( FT_Error )
pfr_extra_item_load_kerning_pairs(FT_Byte * p,FT_Byte * limit,PFR_PhyFont phy_font)590   pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
591                                      FT_Byte*     limit,
592                                      PFR_PhyFont  phy_font )
593   {
594     PFR_KernItem  item;
595     FT_Error      error  = 0;
596     FT_Memory     memory = phy_font->memory;
597 
598 
599     FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
600 
601     if ( FT_NEW( item ) )
602       goto Exit;
603 
604     PFR_CHECK( 4 );
605 
606     item->pair_count = PFR_NEXT_BYTE( p );
607     item->base_adj   = PFR_NEXT_SHORT( p );
608     item->flags      = PFR_NEXT_BYTE( p );
609     item->offset     = phy_font->offset + ( p - phy_font->cursor );
610 
611 #ifndef PFR_CONFIG_NO_CHECKS
612     item->pair_size = 3;
613 
614     if ( item->flags & PFR_KERN_2BYTE_CHAR )
615       item->pair_size += 2;
616 
617     if ( item->flags & PFR_KERN_2BYTE_ADJ )
618       item->pair_size += 1;
619 
620     PFR_CHECK( item->pair_count * item->pair_size );
621 #endif
622 
623     /* load first and last pairs into the item to speed up */
624     /* lookup later...                                     */
625     if ( item->pair_count > 0 )
626     {
627       FT_UInt   char1, char2;
628       FT_Byte*  q;
629 
630 
631       if ( item->flags & PFR_KERN_2BYTE_CHAR )
632       {
633         q     = p;
634         char1 = PFR_NEXT_USHORT( q );
635         char2 = PFR_NEXT_USHORT( q );
636 
637         item->pair1 = PFR_KERN_INDEX( char1, char2 );
638 
639         q = p + item->pair_size * ( item->pair_count - 1 );
640         char1 = PFR_NEXT_USHORT( q );
641         char2 = PFR_NEXT_USHORT( q );
642 
643         item->pair2 = PFR_KERN_INDEX( char1, char2 );
644       }
645       else
646       {
647         q     = p;
648         char1 = PFR_NEXT_BYTE( q );
649         char2 = PFR_NEXT_BYTE( q );
650 
651         item->pair1 = PFR_KERN_INDEX( char1, char2 );
652 
653         q = p + item->pair_size * ( item->pair_count - 1 );
654         char1 = PFR_NEXT_BYTE( q );
655         char2 = PFR_NEXT_BYTE( q );
656 
657         item->pair2 = PFR_KERN_INDEX( char1, char2 );
658       }
659 
660       /* add new item to the current list */
661       item->next                 = NULL;
662       *phy_font->kern_items_tail = item;
663       phy_font->kern_items_tail  = &item->next;
664       phy_font->num_kern_pairs  += item->pair_count;
665     }
666     else
667     {
668       /* empty item! */
669       FT_FREE( item );
670     }
671 
672   Exit:
673     return error;
674 
675   Too_Short:
676     FT_FREE( item );
677 
678     error = PFR_Err_Invalid_Table;
679     FT_ERROR(( "pfr_extra_item_load_kerning_pairs: "
680                "invalid kerning pairs table\n" ));
681     goto Exit;
682   }
683 #endif /* 0 */
684 
685 
686   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
687   {
688     { 1, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_bitmap_info },
689     { 2, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_font_id },
690     { 3, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_stem_snaps },
691     { 4, (PFR_ExtraItem_ParseFunc) pfr_extra_item_load_kerning_pairs },
692     { 0, NULL }
693   };
694 
695 
696   FT_LOCAL_DEF( void )
pfr_phy_font_done(PFR_PhyFont phy_font,FT_Memory memory)697   pfr_phy_font_done( PFR_PhyFont  phy_font,
698                      FT_Memory    memory )
699   {
700     if ( phy_font->font_id )
701       FT_FREE( phy_font->font_id );
702 
703     FT_FREE( phy_font->vertical.stem_snaps );
704     phy_font->vertical.num_stem_snaps = 0;
705 
706     phy_font->horizontal.stem_snaps     = NULL;
707     phy_font->horizontal.num_stem_snaps = 0;
708 
709     FT_FREE( phy_font->strikes );
710     phy_font->num_strikes = 0;
711     phy_font->max_strikes = 0;
712 
713     FT_FREE( phy_font->chars );
714     phy_font->num_chars    = 0;
715     phy_font->chars_offset = 0;
716 
717     FT_FREE( phy_font->blue_values );
718     phy_font->num_blue_values = 0;
719 
720     {
721       PFR_KernItem  item, next;
722 
723 
724       item = phy_font->kern_items;
725       while ( item )
726       {
727         next = item->next;
728         FT_FREE( item );
729         item = next;
730       }
731       phy_font->kern_items      = NULL;
732       phy_font->kern_items_tail = NULL;
733     }
734 
735     phy_font->num_kern_pairs = 0;
736   }
737 
738 
739   FT_LOCAL_DEF( FT_Error )
pfr_phy_font_load(PFR_PhyFont phy_font,FT_Stream stream,FT_UInt32 offset,FT_UInt32 size)740   pfr_phy_font_load( PFR_PhyFont  phy_font,
741                      FT_Stream    stream,
742                      FT_UInt32    offset,
743                      FT_UInt32    size )
744   {
745     FT_Error   error;
746     FT_Memory  memory = stream->memory;
747     FT_UInt    flags, num_aux;
748     FT_Byte*   p;
749     FT_Byte*   limit;
750 
751 
752     phy_font->memory = memory;
753     phy_font->offset = offset;
754 
755     phy_font->kern_items      = NULL;
756     phy_font->kern_items_tail = &phy_font->kern_items;
757 
758     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
759       goto Exit;
760 
761     phy_font->cursor = stream->cursor;
762 
763     p     = stream->cursor;
764     limit = p + size;
765 
766     PFR_CHECK( 15 );
767     phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
768     phy_font->outline_resolution = PFR_NEXT_USHORT( p );
769     phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
770     phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
771     phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
772     phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
773     phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
774     phy_font->flags      = flags = PFR_NEXT_BYTE( p );
775 
776     /* get the standard advance for non-proprotional fonts */
777     if ( !(flags & PFR_PHY_PROPORTIONAL) )
778     {
779       PFR_CHECK( 2 );
780       phy_font->standard_advance = PFR_NEXT_SHORT( p );
781     }
782 
783     /* load the extra items when present */
784     if ( flags & PFR_PHY_EXTRA_ITEMS )
785     {
786       error =  pfr_extra_items_parse( &p, limit,
787                                       pfr_phy_font_extra_items, phy_font );
788 
789       if ( error )
790         goto Fail;
791     }
792 
793     /* skip the aux bytes */
794     PFR_CHECK( 3 );
795     num_aux = PFR_NEXT_ULONG( p );
796 
797     PFR_CHECK( num_aux );
798     p += num_aux;
799 
800     /* read the blue values */
801     {
802       FT_UInt  n, count;
803 
804       PFR_CHECK( 1 );
805       phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
806 
807       PFR_CHECK( count * 2 );
808 
809       if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
810         goto Fail;
811 
812       for ( n = 0; n < count; n++ )
813         phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
814     }
815 
816     PFR_CHECK( 8 );
817     phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
818     phy_font->blue_scale = PFR_NEXT_BYTE( p );
819 
820     phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
821     phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
822 
823     /* read the character descriptors */
824     {
825       FT_UInt  n, count, Size;
826 
827 
828       phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
829       phy_font->chars_offset = offset + ( p - stream->cursor );
830 
831       if ( FT_NEW_ARRAY( phy_font->chars, count ) )
832         goto Fail;
833 
834       Size = 1 + 1 + 2;
835       if ( flags & PFR_PHY_2BYTE_CHARCODE )
836         Size += 1;
837 
838       if ( flags & PFR_PHY_PROPORTIONAL )
839         Size += 2;
840 
841       if ( flags & PFR_PHY_ASCII_CODE )
842         Size += 1;
843 
844       if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
845         Size += 1;
846 
847       if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
848         Size += 1;
849 
850       PFR_CHECK( count * Size );
851 
852       for ( n = 0; n < count; n++ )
853       {
854         PFR_Char  cur = &phy_font->chars[n];
855 
856 
857         cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
858                          ? PFR_NEXT_USHORT( p )
859                          : PFR_NEXT_BYTE( p );
860 
861         cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
862                          ? PFR_NEXT_SHORT( p )
863                          : (FT_Int) phy_font->standard_advance;
864 
865 #if 0
866         cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
867                          ? PFR_NEXT_BYTE( p )
868                          : 0;
869 #else
870         if ( flags & PFR_PHY_ASCII_CODE )
871           p += 1;
872 #endif
873         cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
874                          ? PFR_NEXT_USHORT( p )
875                          : PFR_NEXT_BYTE( p );
876 
877         cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
878                           ? PFR_NEXT_ULONG( p )
879                           : PFR_NEXT_USHORT( p );
880       }
881     }
882 
883     /* that's it !! */
884   Fail:
885     FT_FRAME_EXIT();
886 
887     /* save position of bitmap info */
888     phy_font->bct_offset = FT_STREAM_POS();
889     phy_font->cursor     = NULL;
890 
891   Exit:
892     return error;
893 
894   Too_Short:
895     error = PFR_Err_Invalid_Table;
896     FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
897     goto Fail;
898   }
899 
900 
901 /* END */
902