The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / cffload.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffload.c                                                              */
4 /*                                                                         */
5 /*    OpenType and CFF data/program tables loader (body)                   */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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 <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_POSTSCRIPT_NAMES_H
24 #include FT_TRUETYPE_TAGS_H
25
26 #include "cffload.h"
27 #include "cffparse.h"
28
29 #include "cfferrs.h"
30
31
32   /*************************************************************************/
33   /*                                                                       */
34   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
35   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
36   /* messages during execution.                                            */
37   /*                                                                       */
38 #undef  FT_COMPONENT
39 #define FT_COMPONENT  trace_cffload
40
41   /* read a CFF offset from memory */
42   static FT_ULong
43   cff_get_offset( FT_Byte*  p,
44                   FT_Byte   off_size )
45   {
46     FT_ULong  result;
47
48
49     for ( result = 0; off_size > 0; off_size-- )
50     {
51       result <<= 8;
52       result  |= *p++;
53     }
54
55     return result;
56   }
57
58
59   static FT_Error
60   cff_new_index( CFF_Index*  index,
61                  FT_Stream   stream,
62                  FT_Bool     load )
63   {
64     FT_Error   error;
65     FT_Memory  memory = stream->memory;
66     FT_UShort  count;
67
68
69     MEM_Set( index, 0, sizeof ( *index ) );
70
71     index->stream = stream;
72     if ( !READ_UShort( count ) &&
73          count > 0             )
74     {
75       FT_Byte*   p;
76       FT_Byte    offsize;
77       FT_ULong   data_size;
78       FT_ULong*  poff;
79
80
81       /* there is at least one element; read the offset size,           */
82       /* then access the offset table to compute the index's total size */
83       if ( READ_Byte( offsize ) )
84         goto Exit;
85
86       index->stream   = stream;
87       index->count    = count;
88       index->off_size = offsize;
89       data_size       = (FT_ULong)( count + 1 ) * offsize;
90
91       if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
92            ACCESS_Frame( data_size )                          )
93         goto Exit;
94
95       poff = index->offsets;
96       p    = (FT_Byte*)stream->cursor;
97
98       for ( ; (FT_Short)count >= 0; count-- )
99       {
100         poff[0] = cff_get_offset( p, offsize );
101         poff++;
102         p += offsize;
103       }
104
105       FORGET_Frame();
106
107       index->data_offset = FILE_Pos();
108       data_size          = poff[-1] - 1;
109
110       if ( load )
111       {
112         /* load the data */
113         if ( EXTRACT_Frame( data_size, index->bytes ) )
114           goto Exit;
115       }
116       else
117       {
118         /* skip the data */
119         if ( FILE_Skip( data_size ) )
120           goto Exit;
121       }
122     }
123
124   Exit:
125     if ( error )
126       FREE( index->offsets );
127
128     return error;
129   }
130
131
132   static void
133   cff_done_index( CFF_Index*  index )
134   {
135     if ( index->stream )
136     {
137       FT_Stream  stream = index->stream;
138       FT_Memory  memory = stream->memory;
139
140
141       if ( index->bytes )
142         RELEASE_Frame( index->bytes );
143
144       FREE( index->offsets );
145       MEM_Set( index, 0, sizeof ( *index ) );
146     }
147   }
148
149
150   static FT_Error
151   cff_explicit_index( CFF_Index*  index,
152                       FT_Byte***  table )
153   {
154     FT_Error   error  = 0;
155     FT_Memory  memory = index->stream->memory;
156     FT_UInt    n, offset, old_offset;
157     FT_Byte**  t;
158
159
160     *table = 0;
161
162     if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) )
163     {
164       old_offset = 1;
165       for ( n = 0; n <= index->count; n++ )
166       {
167         offset = index->offsets[n];
168         if ( !offset )
169           offset = old_offset;
170
171         t[n] = index->bytes + offset - 1;
172
173         old_offset = offset;
174       }
175       *table = t;
176     }
177
178     return error;
179   }
180
181
182   FT_LOCAL_DEF FT_Error
183   CFF_Access_Element( CFF_Index*  index,
184                       FT_UInt     element,
185                       FT_Byte**   pbytes,
186                       FT_ULong*   pbyte_len )
187   {
188     FT_Error  error = 0;
189
190
191     if ( index && index->count > element )
192     {
193       /* compute start and end offsets */
194       FT_ULong  off1, off2 = 0;
195
196
197       off1 = index->offsets[element];
198       if ( off1 )
199       {
200         do
201         {
202           element++;
203           off2 = index->offsets[element];
204
205         } while ( off2 == 0 && element < index->count );
206
207         if ( !off2 )
208           off1 = 0;
209       }
210
211       /* access element */
212       if ( off1 )
213       {
214         *pbyte_len = off2 - off1;
215
216         if ( index->bytes )
217         {
218           /* this index was completely loaded in memory, that's easy */
219           *pbytes = index->bytes + off1 - 1;
220         }
221         else
222         {
223           /* this index is still on disk/file, access it through a frame */
224           FT_Stream  stream = index->stream;
225
226
227           if ( FILE_Seek( index->data_offset + off1 - 1 ) ||
228                EXTRACT_Frame( off2 - off1, *pbytes )      )
229             goto Exit;
230         }
231       }
232       else
233       {
234         /* empty index element */
235         *pbytes    = 0;
236         *pbyte_len = 0;
237       }
238     }
239     else
240       error = CFF_Err_Invalid_Argument;
241
242   Exit:
243     return error;
244   }
245
246
247   FT_LOCAL_DEF void
248   CFF_Forget_Element( CFF_Index*  index,
249                       FT_Byte**   pbytes )
250   {
251     if ( index->bytes == 0 )
252     {
253       FT_Stream  stream = index->stream;
254
255
256       RELEASE_Frame( *pbytes );
257     }
258   }
259
260
261   FT_LOCAL_DEF FT_String*
262   CFF_Get_Name( CFF_Index*  index,
263                 FT_UInt     element )
264   {
265     FT_Memory   memory = index->stream->memory;
266     FT_Byte*    bytes;
267     FT_ULong    byte_len;
268     FT_Error    error;
269     FT_String*  name = 0;
270
271
272     error = CFF_Access_Element( index, element, &bytes, &byte_len );
273     if ( error )
274       goto Exit;
275
276     if ( !ALLOC( name, byte_len + 1 ) )
277     {
278       MEM_Copy( name, bytes, byte_len );
279       name[byte_len] = 0;
280     }
281     CFF_Forget_Element( index, &bytes );
282
283   Exit:
284     return name;
285   }
286
287
288   FT_LOCAL_DEF FT_String*
289   CFF_Get_String( CFF_Index*          index,
290                   FT_UInt             sid,
291                   PSNames_Interface*  interface )
292   {
293     /* if it is not a standard string, return it */
294     if ( sid > 390 )
295       return CFF_Get_Name( index, sid - 391 );
296
297     /* that's a standard string, fetch a copy from the PSName module */
298     {
299       FT_String*   name       = 0;
300       const char*  adobe_name = interface->adobe_std_strings( sid );
301       FT_UInt      len;
302
303
304       if ( adobe_name )
305       {
306         FT_Memory memory = index->stream->memory;
307         FT_Error  error;
308
309
310         len = (FT_UInt)strlen( adobe_name );
311         if ( !ALLOC( name, len + 1 ) )
312         {
313           MEM_Copy( name, adobe_name, len );
314           name[len] = 0;
315         }
316       }
317
318       return name;
319     }
320   }
321
322
323   /*************************************************************************/
324   /*************************************************************************/
325   /***                                                                   ***/
326   /***   FD Select table support                                         ***/
327   /***                                                                   ***/
328   /*************************************************************************/
329   /*************************************************************************/
330
331
332   static void
333   CFF_Done_FD_Select( CFF_FD_Select*  select,
334                       FT_Stream       stream )
335   {
336     if ( select->data )
337       RELEASE_Frame( select->data );
338
339     select->data_size   = 0;
340     select->format      = 0;
341     select->range_count = 0;
342   }
343
344
345   static FT_Error
346   CFF_Load_FD_Select( CFF_FD_Select*  select,
347                       FT_UInt         num_glyphs,
348                       FT_Stream       stream,
349                       FT_ULong        offset )
350   {
351     FT_Error  error;
352     FT_Byte   format;
353     FT_UInt   num_ranges;
354
355
356     /* read format */
357     if ( FILE_Seek( offset ) || READ_Byte( format ) )
358       goto Exit;
359
360     select->format      = format;
361     select->cache_count = 0;   /* clear cache */
362
363     switch ( format )
364     {
365     case 0:     /* format 0, that's simple */
366       select->data_size = num_glyphs;
367       goto Load_Data;
368
369     case 3:     /* format 3, a tad more complex */
370       if ( READ_UShort( num_ranges ) )
371         goto Exit;
372
373       select->data_size = num_ranges * 3 + 2;
374
375     Load_Data:
376       if ( EXTRACT_Frame( select->data_size, select->data ) )
377         goto Exit;
378       break;
379
380     default:    /* hmm... that's wrong */
381       error = CFF_Err_Invalid_File_Format;
382     }
383
384   Exit:
385     return error;
386   }
387
388
389   FT_LOCAL_DEF FT_Byte
390   CFF_Get_FD( CFF_FD_Select*  select,
391               FT_UInt         glyph_index )
392   {
393     FT_Byte  fd = 0;
394
395
396     switch ( select->format )
397     {
398     case 0:
399       fd = select->data[glyph_index];
400       break;
401
402     case 3:
403       /* first, compare to cache */
404       if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count )
405       {
406         fd = select->cache_fd;
407         break;
408       }
409
410       /* then, lookup the ranges array */
411       {
412         FT_Byte*  p       = select->data;
413         FT_Byte*  p_limit = p + select->data_size;
414         FT_Byte   fd2;
415         FT_UInt   first, limit;
416
417
418         first = NEXT_UShort( p );
419         do
420         {
421           if ( glyph_index < first )
422             break;
423
424           fd2   = *p++;
425           limit = NEXT_UShort( p );
426
427           if ( glyph_index < limit )
428           {
429             fd = fd2;
430
431             /* update cache */
432             select->cache_first = first;
433             select->cache_count = limit-first;
434             select->cache_fd    = fd2;
435             break;
436           }
437           first = limit;
438
439         } while ( p < p_limit );
440       }
441       break;
442
443     default:
444       ;
445     }
446
447     return fd;
448   }
449
450
451   /*************************************************************************/
452   /*************************************************************************/
453   /***                                                                   ***/
454   /***   CFF font support                                                ***/
455   /***                                                                   ***/
456   /*************************************************************************/
457   /*************************************************************************/
458
459   static void
460   CFF_Done_Encoding( CFF_Encoding*  encoding,
461                      FT_Stream      stream )
462   {
463     FT_Memory  memory = stream->memory;
464
465
466     FREE( encoding->codes );
467     FREE( encoding->sids  );
468     encoding->format = 0;
469     encoding->offset = 0;
470     encoding->codes  = 0;
471     encoding->sids   = 0;
472   }
473
474
475   static void
476   CFF_Done_Charset( CFF_Charset*  charset,
477                     FT_Stream     stream )
478   {
479     FT_Memory  memory = stream->memory;
480
481
482     FREE( charset->sids );
483     charset->format = 0;
484     charset->offset = 0;
485     charset->sids   = 0;
486   }
487
488
489   static FT_Error
490   CFF_Load_Charset( CFF_Charset*  charset,
491                     FT_UInt       num_glyphs,
492                     FT_Stream     stream,
493                     FT_ULong      base_offset,
494                     FT_ULong      offset )
495   {
496     FT_Memory  memory     = stream->memory;
497     FT_Error   error      = 0;
498     FT_UShort  glyph_sid;
499
500
501     charset->offset = base_offset + offset;
502
503     /* Get the format of the table. */
504     if ( FILE_Seek( charset->offset ) ||
505          READ_Byte( charset->format ) )
506       goto Exit;
507
508     /* If the the offset is greater than 2, we have to parse the */
509     /* charset table.                                            */
510     if ( offset > 2 )
511     {
512       FT_UInt  j;
513
514
515       /* Allocate memory for sids. */
516       if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
517         goto Exit;
518
519       /* assign the .notdef glyph */
520       charset->sids[0] = 0;
521
522       switch ( charset->format )
523       {
524       case 0:
525         for ( j = 1; j < num_glyphs; j++ )
526         {
527           if ( READ_UShort( glyph_sid ) )
528             goto Exit;
529
530           charset->sids[j] = glyph_sid;
531         }
532         break;
533
534       case 1:
535       case 2:
536         {
537           FT_UInt  nleft;
538           FT_UInt  i;
539
540
541           j = 1;
542
543           while ( j < num_glyphs )
544           {
545
546             /* Read the first glyph sid of the range. */
547             if ( READ_UShort( glyph_sid ) )
548               goto Exit;
549
550             /* Read the number of glyphs in the range.  */
551             if ( charset->format == 2 )
552             {
553               if ( READ_UShort( nleft ) )
554                 goto Exit;
555             }
556             else
557             {
558               if ( READ_Byte( nleft ) )
559                 goto Exit;
560             }
561
562             /* Fill in the range of sids -- `nleft + 1' glyphs. */
563             for ( i = 0; i <= nleft; i++, j++, glyph_sid++ )
564               charset->sids[j] = glyph_sid;
565           }
566         }
567         break;
568
569       default:
570         FT_ERROR(( "CFF_Load_Charset: invalid table format!\n" ));
571         error = CFF_Err_Invalid_File_Format;
572         goto Exit;
573       }
574     }
575     else
576     {
577       /* Parse default tables corresponding to offset == 0, 1, or 2.  */
578       /* CFF specification intimates the following:                   */
579       /*                                                              */
580       /* In order to use a predefined charset, the following must be  */
581       /* true: The charset constructed for the glyphs in the font's   */
582       /* charstrings dictionary must match the predefined charset in  */
583       /* the first num_glyphs, and hence must match the predefined    */
584       /* charset *exactly*.                                           */
585
586       switch ( offset )
587       {
588       case 0:
589         if ( num_glyphs != 229 )
590         {
591           FT_ERROR(("CFF_Load_Charset: implicit charset not equal to\n"
592                     "predefined charset (Adobe ISO-Latin)!\n" ));
593           error = CFF_Err_Invalid_File_Format;
594           goto Exit;
595         }
596
597         /* Allocate memory for sids. */
598         if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
599           goto Exit;
600
601         /* Copy the predefined charset into the allocated memory. */
602         MEM_Copy( charset->sids, cff_isoadobe_charset,
603                   num_glyphs * sizeof ( FT_UShort ) );
604
605         break;
606
607       case 1:
608         if ( num_glyphs != 166 )
609         {
610           FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
611                      "predefined charset (Adobe Expert)!\n" ));
612           error = CFF_Err_Invalid_File_Format;
613           goto Exit;
614         }
615
616         /* Allocate memory for sids. */
617         if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
618           goto Exit;
619
620         /* Copy the predefined charset into the allocated memory.     */
621         MEM_Copy( charset->sids, cff_expert_charset,
622                   num_glyphs * sizeof ( FT_UShort ) );
623
624         break;
625
626       case 2:
627         if ( num_glyphs != 87 )
628         {
629           FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to\n"
630                      "predefined charset (Adobe Expert Subset)!\n" ));
631           error = CFF_Err_Invalid_File_Format;
632           goto Exit;
633         }
634
635         /* Allocate memory for sids. */
636         if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
637           goto Exit;
638
639         /* Copy the predefined charset into the allocated memory.     */
640         MEM_Copy( charset->sids, cff_expertsubset_charset,
641                   num_glyphs * sizeof ( FT_UShort ) );
642
643         break;
644
645       default:
646         error = CFF_Err_Invalid_File_Format;
647         goto Exit;
648       }
649     }
650
651   Exit:
652
653     /* Clean up if there was an error. */
654     if ( error )
655       if ( charset->sids )
656       {
657         if ( charset->sids )
658           FREE( charset->sids );
659         charset->format = 0;
660         charset->offset = 0;
661         charset->sids   = 0;
662       }
663
664     return error;
665   }
666
667
668   static FT_Error
669   CFF_Load_Encoding( CFF_Encoding*  encoding,
670                      CFF_Charset*   charset,
671                      FT_UInt        num_glyphs,
672                      FT_Stream      stream,
673                      FT_ULong       base_offset,
674                      FT_ULong       offset )
675   {
676     FT_Memory   memory = stream->memory;
677     FT_Error    error  = 0;
678     FT_UInt     count;
679     FT_UInt     j;
680     FT_UShort   glyph_sid;
681     FT_Byte     glyph_code;
682
683
684     /* Check for charset->sids.  If we do not have this, we fail. */
685     if ( !charset->sids )
686     {
687       error = CFF_Err_Invalid_File_Format;
688       goto Exit;
689     }
690
691     /* Allocate memory for sids/codes -- there are at most 256 sids/codes */
692     /* for an encoding.                                                   */
693     if ( ALLOC( encoding->sids,  256 * sizeof ( FT_UShort ) ) ||
694          ALLOC( encoding->codes, 256 * sizeof ( FT_UShort ) ) )
695       goto Exit;
696
697     /* Zero out the code to gid/sid mappings. */
698     for ( j = 0; j < 255; j++ )
699     {
700       encoding->sids [j] = 0;
701       encoding->codes[j] = 0;
702     }
703
704     /* Note: The encoding table in a CFF font is indexed by glyph index,  */
705     /* where the first encoded glyph index is 1.  Hence, we read the char */
706     /* code (`glyph_code') at index j and make the assignment:            */
707     /*                                                                    */
708     /*    encoding->codes[glyph_code] = j + 1                             */
709     /*                                                                    */
710     /* We also make the assignment:                                       */
711     /*                                                                    */
712     /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
713     /*                                                                    */
714     /* This gives us both a code to GID and a code to SID mapping.        */
715
716     if ( offset > 1 )
717     {
718
719       encoding->offset = base_offset + offset;
720
721       /* we need to parse the table to determine its size */
722       if ( FILE_Seek( encoding->offset ) ||
723            READ_Byte( encoding->format ) ||
724            READ_Byte( count )            )
725         goto Exit;
726
727       switch ( encoding->format & 0x7F )
728       {
729       case 0:
730         for ( j = 1; j <= count; j++ )
731         {
732           if ( READ_Byte( glyph_code ) )
733             goto Exit;
734
735           /* Make sure j is not too big. */
736           if ( j > num_glyphs )
737             goto Exit;
738
739           /* Assign code to GID mapping. */
740           encoding->codes[glyph_code] = (FT_UShort)j;
741
742           /* Assign code to SID mapping. */
743           encoding->sids[glyph_code] = charset->sids[j];
744         }
745
746         break;
747
748       case 1:
749         {
750           FT_Byte  nleft;
751           FT_UInt  i = 1;
752           FT_UInt  k;
753
754
755           /* Parse the Format1 ranges. */
756           for ( j = 0;  j < count; j++, i += nleft )
757           {
758             /* Read the first glyph code of the range. */
759             if ( READ_Byte( glyph_code ) )
760               goto Exit;
761
762             /* Read the number of codes in the range. */
763             if ( READ_Byte( nleft ) )
764               goto Exit;
765
766             /* Increment nleft, so we read `nleft + 1' codes/sids. */
767             nleft++;
768
769             /* Fill in the range of codes/sids. */
770             for ( k = i; k < nleft + i; k++, glyph_code++ )
771             {
772               /* Make sure k is not too big. */
773               if ( k > num_glyphs )
774                 goto Exit;
775
776               /* Assign code to GID mapping. */
777               encoding->codes[glyph_code] = (FT_UShort)k;
778
779               /* Assign code to SID mapping. */
780               encoding->sids[glyph_code] = charset->sids[k];
781             }
782           }
783         }
784         break;
785
786       default:
787         FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
788         error = CFF_Err_Invalid_File_Format;
789         goto Exit;
790       }
791
792       /* Parse supplemental encodings, if any. */
793       if ( encoding->format & 0x80 )
794       {
795         FT_UInt glyph_id;
796
797
798         /* count supplements */
799         if ( READ_Byte( count ) )
800           goto Exit;
801
802         for ( j = 0; j < count; j++ )
803         {
804           /* Read supplemental glyph code. */
805           if ( READ_Byte( glyph_code ) )
806             goto Exit;
807
808           /* Read the SID associated with this glyph code. */
809           if ( READ_UShort( glyph_sid ) )
810             goto Exit;
811
812           /* Assign code to SID mapping. */
813           encoding->sids[glyph_code] = glyph_sid;
814
815           /* First, lookup GID which has been assigned to */
816           /* SID glyph_sid.                               */
817           for ( glyph_id = 0; glyph_id < num_glyphs; glyph_id++ )
818           {
819             if ( charset->sids[glyph_id] == glyph_sid )
820               break;
821           }
822
823           /* Now, make the assignment. */
824           encoding->codes[glyph_code] = (FT_UShort)glyph_id;
825         }
826       }
827     }
828     else
829     {
830       FT_UInt i;
831
832
833       /* We take into account the fact a CFF font can use a predefined  */
834       /* encoding without containing all of the glyphs encoded by this  */
835       /* encoding (see the note at the end of section 12 in the CFF     */
836       /* specification).                                                */
837
838       switch ( offset )
839       {
840       case 0:
841         /* First, copy the code to SID mapping. */
842         MEM_Copy( encoding->sids, cff_standard_encoding,
843                   256 * sizeof ( FT_UShort ) );
844
845         /* Construct code to GID mapping from code */
846         /* to SID mapping and charset.             */
847         for ( j = 0; j < 256; j++ )
848         {
849           /* If j is encoded, find the GID for it. */
850           if ( encoding->sids[j] )
851           {
852             for ( i = 1; i < num_glyphs; i++ )
853               /* We matched, so break. */
854               if ( charset->sids[i] == encoding->sids[j] )
855                 break;
856
857             /* i will be equal to num_glyphs if we exited the above */
858             /* loop without a match.  In this case, we also have to */
859             /* fix the code to SID mapping.                         */
860             if ( i == num_glyphs )
861             {
862               encoding->codes[j] = 0;
863               encoding->sids [j] = 0;
864             }
865             else
866               encoding->codes[j] = (FT_UShort)i;
867           }
868         }
869         break;
870
871       case 1:
872         /* First, copy the code to SID mapping. */
873         MEM_Copy( encoding->sids, cff_expert_encoding,
874                   256 * sizeof ( FT_UShort ) );
875
876         /* Construct code to GID mapping from code to SID mapping */
877         /* and charset.                                           */
878         for ( j = 0; j < 256; j++ )
879         {
880           /* If j is encoded, find the GID for it. */
881           if ( encoding->sids[j] )
882           {
883             for ( i = 1; i < num_glyphs; i++ )
884               /* We matched, so break. */
885               if ( charset->sids[i] == encoding->sids[j] )
886                 break;
887
888             /* i will be equal to num_glyphs if we exited the above */
889             /* loop without a match.  In this case, we also have to */
890             /* fix the code to SID mapping.                         */
891             if ( i == num_glyphs )
892             {
893               encoding->codes[j] = 0;
894               encoding->sids [j] = 0;
895             }
896             else
897               encoding->codes[j] = (FT_UShort)i;
898           }
899         }
900         break;
901
902       default:
903         FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
904         error = CFF_Err_Invalid_File_Format;
905         goto Exit;
906       }
907     }
908
909   Exit:
910
911     /* Clean up if there was an error. */
912     if ( error )
913     {
914       if ( encoding->sids || encoding->codes )
915       {
916         if ( encoding->sids )
917           FREE( encoding->sids );
918
919         if ( encoding->codes )
920           FREE( encoding->codes );
921
922         charset->format = 0;
923         charset->offset = 0;
924         charset->sids   = 0;
925       }
926     }
927
928     return error;
929   }
930
931
932   static FT_Error
933   CFF_Load_SubFont( CFF_SubFont*  font,
934                     CFF_Index*    index,
935                     FT_UInt       font_index,
936                     FT_Stream     stream,
937                     FT_ULong      base_offset )
938   {
939     FT_Error        error;
940     CFF_Parser      parser;
941     FT_Byte*        dict;
942     FT_ULong        dict_len;
943     CFF_Font_Dict*  top  = &font->font_dict;
944     CFF_Private*    priv = &font->private_dict;
945
946
947     CFF_Parser_Init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
948
949     /* set defaults */
950     MEM_Set( top, 0, sizeof ( *top ) );
951
952     top->underline_position  = -100;
953     top->underline_thickness = 50;
954     top->charstring_type     = 2;
955     top->font_matrix.xx      = 0x10000L;
956     top->font_matrix.yy      = 0x10000L;
957     top->cid_count           = 8720;
958
959     error = CFF_Access_Element( index, font_index, &dict, &dict_len ) ||
960             CFF_Parser_Run( &parser, dict, dict + dict_len );
961
962     CFF_Forget_Element( index, &dict );
963
964     if ( error )
965       goto Exit;
966
967     /* if it is a CID font, we stop there */
968     if ( top->cid_registry )
969       goto Exit;
970
971     /* parse the private dictionary, if any */
972     if ( top->private_offset && top->private_size )
973     {
974       /* set defaults */
975       MEM_Set( priv, 0, sizeof ( *priv ) );
976
977       priv->blue_shift       = 7;
978       priv->blue_fuzz        = 1;
979       priv->lenIV            = -1;
980       priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
981       priv->blue_scale       = (FT_Fixed)0.039625 * 0x10000L;
982
983       CFF_Parser_Init( &parser, CFF_CODE_PRIVATE, priv );
984
985       if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
986            ACCESS_Frame( font->font_dict.private_size )              )
987         goto Exit;
988
989       error = CFF_Parser_Run( &parser,
990                              (FT_Byte*)stream->cursor,
991                              (FT_Byte*)stream->limit );
992       FORGET_Frame();
993       if ( error )
994         goto Exit;
995     }
996
997     /* read the local subrs, if any */
998     if ( priv->local_subrs_offset )
999     {
1000       if ( FILE_Seek( base_offset + top->private_offset +
1001                       priv->local_subrs_offset ) )
1002         goto Exit;
1003
1004       error = cff_new_index( &font->local_subrs_index, stream, 1 );
1005       if ( error )
1006         goto Exit;
1007
1008       font->num_local_subrs = font->local_subrs_index.count;
1009       error = cff_explicit_index( &font->local_subrs_index,
1010                                      &font->local_subrs );
1011       if ( error )
1012         goto Exit;
1013     }
1014
1015   Exit:
1016     return error;
1017   }
1018
1019
1020   static void
1021   CFF_Done_SubFont( FT_Memory     memory,
1022                     CFF_SubFont*  subfont )
1023   {
1024     if ( subfont )
1025     {
1026       cff_done_index( &subfont->local_subrs_index );
1027       FREE( subfont->local_subrs );
1028     }
1029   }
1030
1031
1032   FT_LOCAL_DEF FT_Error
1033   CFF_Load_Font( FT_Stream  stream,
1034                  FT_Int     face_index,
1035                  CFF_Font*  font )
1036   {
1037     static const FT_Frame_Field  cff_header_fields[] =
1038     {
1039 #undef  FT_STRUCTURE
1040 #define FT_STRUCTURE  CFF_Font
1041
1042       FT_FRAME_START( 4 ),
1043         FT_FRAME_BYTE( version_major ),
1044         FT_FRAME_BYTE( version_minor ),
1045         FT_FRAME_BYTE( header_size ),
1046         FT_FRAME_BYTE( absolute_offsize ),
1047       FT_FRAME_END
1048     };
1049
1050     FT_Error        error;
1051     FT_Memory       memory = stream->memory;
1052     FT_ULong        base_offset;
1053     CFF_Font_Dict*  dict;
1054
1055
1056     MEM_Set( font, 0, sizeof ( *font ) );
1057
1058     font->stream = stream;
1059     font->memory = memory;
1060     dict         = &font->top_font.font_dict;
1061     base_offset  = FILE_Pos();
1062
1063     /* read CFF font header */
1064     if ( READ_Fields( cff_header_fields, font ) )
1065       goto Exit;
1066
1067     /* check format */
1068     if ( font->version_major   != 1 ||
1069          font->header_size      < 4 ||
1070          font->absolute_offsize > 4 )
1071     {
1072       FT_TRACE2(( "[not a CFF font header!]\n" ));
1073       error = CFF_Err_Unknown_File_Format;
1074       goto Exit;
1075     }
1076
1077     /* skip the rest of the header */
1078     if ( FILE_Skip( font->header_size - 4 ) )
1079       goto Exit;
1080
1081     /* read the name, top dict, string and global subrs index */
1082     if ( FT_SET_ERROR( cff_new_index( &font->name_index,         stream, 0 )) ||
1083          FT_SET_ERROR( cff_new_index( &font->font_dict_index,    stream, 0 )) ||
1084          FT_SET_ERROR( cff_new_index( &font->string_index,       stream, 0 )) ||
1085          FT_SET_ERROR( cff_new_index( &font->global_subrs_index, stream, 1 )) )
1086       goto Exit;
1087
1088     /* well, we don't really forget the `disabled' fonts... */
1089     font->num_faces = font->name_index.count;
1090     if ( face_index >= (FT_Int)font->num_faces )
1091     {
1092       FT_ERROR(( "CFF_Load_Font: incorrect face index = %d\n",
1093                  face_index ));
1094       error = CFF_Err_Invalid_Argument;
1095     }
1096
1097     /* in case of a font format check, simply exit now */
1098     if ( face_index < 0 )
1099       goto Exit;
1100
1101     /* now, parse the top-level font dictionary */
1102     error = CFF_Load_SubFont( &font->top_font,
1103                               &font->font_dict_index,
1104                               face_index,
1105                               stream,
1106                               base_offset );
1107     if ( error )
1108       goto Exit;
1109
1110     /* now, check for a CID font */
1111     if ( dict->cid_registry )
1112     {
1113       CFF_Index     fd_index;
1114       CFF_SubFont*  sub;
1115       FT_UInt       index;
1116
1117
1118       /* this is a CID-keyed font, we must now allocate a table of */
1119       /* sub-fonts, then load each of them separately              */
1120       if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
1121         goto Exit;
1122
1123       error = cff_new_index( &fd_index, stream, 0 );
1124       if ( error )
1125         goto Exit;
1126
1127       if ( fd_index.count > CFF_MAX_CID_FONTS )
1128       {
1129         FT_ERROR(( "CFF_Load_Font: FD array too large in CID font\n" ));
1130         goto Fail_CID;
1131       }
1132
1133       /* allocate & read each font dict independently */
1134       font->num_subfonts = fd_index.count;
1135       if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
1136         goto Fail_CID;
1137
1138       /* setup pointer table */
1139       for ( index = 0; index < fd_index.count; index++ )
1140         font->subfonts[index] = sub + index;
1141
1142       /* now load each sub font independently */
1143       for ( index = 0; index < fd_index.count; index++ )
1144       {
1145         sub = font->subfonts[index];
1146         error = CFF_Load_SubFont( sub, &fd_index, index,
1147                                   stream, base_offset );
1148         if ( error )
1149           goto Fail_CID;
1150       }
1151
1152       /* now load the FD Select array */
1153       error = CFF_Load_FD_Select( &font->fd_select,
1154                                   dict->cid_count,
1155                                   stream,
1156                                   base_offset + dict->cid_fd_select_offset );
1157
1158     Fail_CID:
1159       cff_done_index( &fd_index );
1160
1161       if ( error )
1162         goto Exit;
1163     }
1164     else
1165       font->num_subfonts = 0;
1166
1167     /* read the charstrings index now */
1168     if ( dict->charstrings_offset == 0 )
1169     {
1170       FT_ERROR(( "CFF_Load_Font: no charstrings offset!\n" ));
1171       error = CFF_Err_Unknown_File_Format;
1172       goto Exit;
1173     }
1174
1175     if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
1176       goto Exit;
1177
1178     error = cff_new_index( &font->charstrings_index, stream, 0 );
1179     if ( error )
1180       goto Exit;
1181
1182     /* explicit the global subrs */
1183     font->num_global_subrs = font->global_subrs_index.count;
1184     font->num_glyphs       = font->charstrings_index.count;
1185
1186     error = cff_explicit_index( &font->global_subrs_index,
1187                                 &font->global_subrs ) ;
1188
1189     if ( error )
1190       goto Exit;
1191
1192     /* read the Charset and Encoding tables when available */
1193     error = CFF_Load_Charset( &font->charset, font->num_glyphs, stream,
1194                               base_offset, dict->charset_offset );
1195     if ( error )
1196       goto Exit;
1197
1198     error = CFF_Load_Encoding( &font->encoding,
1199                                &font->charset,
1200                                font->num_glyphs,
1201                                stream,
1202                                base_offset,
1203                                dict->encoding_offset );
1204     if ( error )
1205       goto Exit;
1206
1207     /* get the font name */
1208     font->font_name = CFF_Get_Name( &font->name_index, face_index );
1209
1210   Exit:
1211     return error;
1212   }
1213
1214
1215   FT_LOCAL_DEF void
1216   CFF_Done_Font( CFF_Font*  font )
1217   {
1218     FT_Memory  memory = font->memory;
1219     FT_UInt    index;
1220
1221
1222     cff_done_index( &font->global_subrs_index );
1223     cff_done_index( &font->string_index );
1224     cff_done_index( &font->font_dict_index );
1225     cff_done_index( &font->name_index );
1226     cff_done_index( &font->charstrings_index );
1227
1228     /* release font dictionaries */
1229     for ( index = 0; index < font->num_subfonts; index++ )
1230       CFF_Done_SubFont( memory, font->subfonts[index] );
1231
1232     CFF_Done_Encoding( &font->encoding, font->stream );
1233     CFF_Done_Charset( &font->charset, font->stream );
1234
1235     CFF_Done_SubFont( memory, &font->top_font );
1236
1237     CFF_Done_FD_Select( &font->fd_select, font->stream );
1238
1239     FREE( font->global_subrs );
1240     FREE( font->font_name );
1241   }
1242
1243
1244 /* END */