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 /***************************************************************************/
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
26 #include "cffload.h"
27 #include "cffparse.h"
29 #include "cfferrs.h"
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
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;
49 for ( result = 0; off_size > 0; off_size-- )
50 {
51 result <<= 8;
52 result |= *p++;
53 }
55 return result;
56 }
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;
69 MEM_Set( index, 0, sizeof ( *index ) );
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;
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;
86 index->stream = stream;
87 index->count = count;
88 index->off_size = offsize;
89 data_size = (FT_ULong)( count + 1 ) * offsize;
91 if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) ||
92 ACCESS_Frame( data_size ) )
93 goto Exit;
95 poff = index->offsets;
96 p = (FT_Byte*)stream->cursor;
98 for ( ; (FT_Short)count >= 0; count-- )
99 {
100 poff[0] = cff_get_offset( p, offsize );
101 poff++;
102 p += offsize;
103 }
105 FORGET_Frame();
107 index->data_offset = FILE_Pos();
108 data_size = poff[-1] - 1;
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 }
124 Exit:
125 if ( error )
126 FREE( index->offsets );
128 return error;
129 }
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;
141 if ( index->bytes )
142 RELEASE_Frame( index->bytes );
144 FREE( index->offsets );
145 MEM_Set( index, 0, sizeof ( *index ) );
146 }
147 }
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;
160 *table = 0;
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;
171 t[n] = index->bytes + offset - 1;
173 old_offset = offset;
174 }
175 *table = t;
176 }
178 return error;
179 }
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;
191 if ( index && index->count > element )
192 {
193 /* compute start and end offsets */
194 FT_ULong off1, off2 = 0;
197 off1 = index->offsets[element];
198 if ( off1 )
199 {
200 do
201 {
202 element++;
203 off2 = index->offsets[element];
205 } while ( off2 == 0 && element < index->count );
207 if ( !off2 )
208 off1 = 0;
209 }
211 /* access element */
212 if ( off1 )
213 {
214 *pbyte_len = off2 - off1;
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;
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;
242 Exit:
243 return error;
244 }
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;
256 RELEASE_Frame( *pbytes );
257 }
258 }
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;
272 error = CFF_Access_Element( index, element, &bytes, &byte_len );
273 if ( error )
274 goto Exit;
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 );
283 Exit:
284 return name;
285 }
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 );
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;
304 if ( adobe_name )
305 {
306 FT_Memory memory = index->stream->memory;
307 FT_Error error;
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 }
318 return name;
319 }
320 }
323 /*************************************************************************/
324 /*************************************************************************/
325 /*** ***/
326 /*** FD Select table support ***/
327 /*** ***/
328 /*************************************************************************/
329 /*************************************************************************/
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 );
339 select->data_size = 0;
340 select->format = 0;
341 select->range_count = 0;
342 }
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;
356 /* read format */
357 if ( FILE_Seek( offset ) || READ_Byte( format ) )
358 goto Exit;
360 select->format = format;
361 select->cache_count = 0; /* clear cache */
363 switch ( format )
364 {
365 case 0: /* format 0, that's simple */
366 select->data_size = num_glyphs;
367 goto Load_Data;
369 case 3: /* format 3, a tad more complex */
370 if ( READ_UShort( num_ranges ) )
371 goto Exit;
373 select->data_size = num_ranges * 3 + 2;
375 Load_Data:
376 if ( EXTRACT_Frame( select->data_size, select->data ) )
377 goto Exit;
378 break;
380 default: /* hmm... that's wrong */
381 error = CFF_Err_Invalid_File_Format;
382 }
384 Exit:
385 return error;
386 }
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;
396 switch ( select->format )
397 {
398 case 0:
399 fd = select->data[glyph_index];
400 break;
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 }
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;
418 first = NEXT_UShort( p );
419 do
420 {
421 if ( glyph_index < first )
422 break;
424 fd2 = *p++;
425 limit = NEXT_UShort( p );
427 if ( glyph_index < limit )
428 {
429 fd = fd2;
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;
439 } while ( p < p_limit );
440 }
441 break;
443 default:
444 ;
445 }
447 return fd;
448 }
451 /*************************************************************************/
452 /*************************************************************************/
453 /*** ***/
454 /*** CFF font support ***/
455 /*** ***/
456 /*************************************************************************/
457 /*************************************************************************/
459 static void
460 CFF_Done_Encoding( CFF_Encoding* encoding,
461 FT_Stream stream )
462 {
463 FT_Memory memory = stream->memory;
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 }
475 static void
476 CFF_Done_Charset( CFF_Charset* charset,
477 FT_Stream stream )
478 {
479 FT_Memory memory = stream->memory;
482 FREE( charset->sids );
483 charset->format = 0;
484 charset->offset = 0;
485 charset->sids = 0;
486 }
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;
501 charset->offset = base_offset + offset;
503 /* Get the format of the table. */
504 if ( FILE_Seek( charset->offset ) ||
505 READ_Byte( charset->format ) )
506 goto Exit;
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;
515 /* Allocate memory for sids. */
516 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
517 goto Exit;
519 /* assign the .notdef glyph */
520 charset->sids[0] = 0;
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;
530 charset->sids[j] = glyph_sid;
531 }
532 break;
534 case 1:
535 case 2:
536 {
537 FT_UInt nleft;
538 FT_UInt i;
541 j = 1;
543 while ( j < num_glyphs )
544 {
546 /* Read the first glyph sid of the range. */
547 if ( READ_UShort( glyph_sid ) )
548 goto Exit;
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 }
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;
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*. */
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 }
597 /* Allocate memory for sids. */
598 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
599 goto Exit;
601 /* Copy the predefined charset into the allocated memory. */
602 MEM_Copy( charset->sids, cff_isoadobe_charset,
603 num_glyphs * sizeof ( FT_UShort ) );
605 break;
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 }
616 /* Allocate memory for sids. */
617 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
618 goto Exit;
620 /* Copy the predefined charset into the allocated memory. */
621 MEM_Copy( charset->sids, cff_expert_charset,
622 num_glyphs * sizeof ( FT_UShort ) );
624 break;
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 }
635 /* Allocate memory for sids. */
636 if ( ALLOC( charset->sids, num_glyphs * sizeof ( FT_UShort ) ) )
637 goto Exit;
639 /* Copy the predefined charset into the allocated memory. */
640 MEM_Copy( charset->sids, cff_expertsubset_charset,
641 num_glyphs * sizeof ( FT_UShort ) );
643 break;
645 default:
646 error = CFF_Err_Invalid_File_Format;
647 goto Exit;
648 }
649 }
651 Exit:
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 }
664 return error;
665 }
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;
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 }
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;
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 }
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. */
716 if ( offset > 1 )
717 {
719 encoding->offset = base_offset + offset;
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;
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;
735 /* Make sure j is not too big. */
736 if ( j > num_glyphs )
737 goto Exit;
739 /* Assign code to GID mapping. */
740 encoding->codes[glyph_code] = (FT_UShort)j;
742 /* Assign code to SID mapping. */
743 encoding->sids[glyph_code] = charset->sids[j];
744 }
746 break;
748 case 1:
749 {
750 FT_Byte nleft;
751 FT_UInt i = 1;
752 FT_UInt k;
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;
762 /* Read the number of codes in the range. */
763 if ( READ_Byte( nleft ) )
764 goto Exit;
766 /* Increment nleft, so we read `nleft + 1' codes/sids. */
767 nleft++;
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;
776 /* Assign code to GID mapping. */
777 encoding->codes[glyph_code] = (FT_UShort)k;
779 /* Assign code to SID mapping. */
780 encoding->sids[glyph_code] = charset->sids[k];
781 }
782 }
783 }
784 break;
786 default:
787 FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
788 error = CFF_Err_Invalid_File_Format;
789 goto Exit;
790 }
792 /* Parse supplemental encodings, if any. */
793 if ( encoding->format & 0x80 )
794 {
795 FT_UInt glyph_id;
798 /* count supplements */
799 if ( READ_Byte( count ) )
800 goto Exit;
802 for ( j = 0; j < count; j++ )
803 {
804 /* Read supplemental glyph code. */
805 if ( READ_Byte( glyph_code ) )
806 goto Exit;
808 /* Read the SID associated with this glyph code. */
809 if ( READ_UShort( glyph_sid ) )
810 goto Exit;
812 /* Assign code to SID mapping. */
813 encoding->sids[glyph_code] = glyph_sid;
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 }
823 /* Now, make the assignment. */
824 encoding->codes[glyph_code] = (FT_UShort)glyph_id;
825 }
826 }
827 }
828 else
829 {
830 FT_UInt i;
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). */
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 ) );
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;
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;
871 case 1:
872 /* First, copy the code to SID mapping. */
873 MEM_Copy( encoding->sids, cff_expert_encoding,
874 256 * sizeof ( FT_UShort ) );
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;
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;
902 default:
903 FT_ERROR(( "CFF_Load_Encoding: invalid table format!\n" ));
904 error = CFF_Err_Invalid_File_Format;
905 goto Exit;
906 }
907 }
909 Exit:
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 );
919 if ( encoding->codes )
920 FREE( encoding->codes );
922 charset->format = 0;
923 charset->offset = 0;
924 charset->sids = 0;
925 }
926 }
928 return error;
929 }
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;
947 CFF_Parser_Init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
949 /* set defaults */
950 MEM_Set( top, 0, sizeof ( *top ) );
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;
959 error = CFF_Access_Element( index, font_index, &dict, &dict_len ) ||
960 CFF_Parser_Run( &parser, dict, dict + dict_len );
962 CFF_Forget_Element( index, &dict );
964 if ( error )
965 goto Exit;
967 /* if it is a CID font, we stop there */
968 if ( top->cid_registry )
969 goto Exit;
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 ) );
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;
983 CFF_Parser_Init( &parser, CFF_CODE_PRIVATE, priv );
985 if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
986 ACCESS_Frame( font->font_dict.private_size ) )
987 goto Exit;
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 }
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;
1004 error = cff_new_index( &font->local_subrs_index, stream, 1 );
1005 if ( error )
1006 goto Exit;
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 }
1015 Exit:
1016 return error;
1017 }
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 }
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
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 };
1050 FT_Error error;
1051 FT_Memory memory = stream->memory;
1052 FT_ULong base_offset;
1053 CFF_Font_Dict* dict;
1056 MEM_Set( font, 0, sizeof ( *font ) );
1058 font->stream = stream;
1059 font->memory = memory;
1060 dict = &font->top_font.font_dict;
1061 base_offset = FILE_Pos();
1063 /* read CFF font header */
1064 if ( READ_Fields( cff_header_fields, font ) )
1065 goto Exit;
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 }
1077 /* skip the rest of the header */
1078 if ( FILE_Skip( font->header_size - 4 ) )
1079 goto Exit;
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;
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 }
1097 /* in case of a font format check, simply exit now */
1098 if ( face_index < 0 )
1099 goto Exit;
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;
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;
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;
1123 error = cff_new_index( &fd_index, stream, 0 );
1124 if ( error )
1125 goto Exit;
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 }
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;
1138 /* setup pointer table */
1139 for ( index = 0; index < fd_index.count; index++ )
1140 font->subfonts[index] = sub + index;
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 }
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 );
1158 Fail_CID:
1159 cff_done_index( &fd_index );
1161 if ( error )
1162 goto Exit;
1163 }
1164 else
1165 font->num_subfonts = 0;
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 }
1175 if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
1176 goto Exit;
1178 error = cff_new_index( &font->charstrings_index, stream, 0 );
1179 if ( error )
1180 goto Exit;
1182 /* explicit the global subrs */
1183 font->num_global_subrs = font->global_subrs_index.count;
1184 font->num_glyphs = font->charstrings_index.count;
1186 error = cff_explicit_index( &font->global_subrs_index,
1187 &font->global_subrs ) ;
1189 if ( error )
1190 goto Exit;
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;
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;
1207 /* get the font name */
1208 font->font_name = CFF_Get_Name( &font->name_index, face_index );
1210 Exit:
1211 return error;
1212 }
1215 FT_LOCAL_DEF void
1216 CFF_Done_Font( CFF_Font* font )
1217 {
1218 FT_Memory memory = font->memory;
1219 FT_UInt index;
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 );
1228 /* release font dictionaries */
1229 for ( index = 0; index < font->num_subfonts; index++ )
1230 CFF_Done_SubFont( memory, font->subfonts[index] );
1232 CFF_Done_Encoding( &font->encoding, font->stream );
1233 CFF_Done_Charset( &font->charset, font->stream );
1235 CFF_Done_SubFont( memory, &font->top_font );
1237 CFF_Done_FD_Select( &font->fd_select, font->stream );
1239 FREE( font->global_subrs );
1240 FREE( font->font_name );
1241 }
1244 /* END */