]> git.saurik.com Git - wxWidgets.git/blame - src/freetype/type1z/z1parse.c
attempts at making modal dialogs without parent work - failed
[wxWidgets.git] / src / freetype / type1z / z1parse.c
CommitLineData
cabec872
RR
1/***************************************************************************/
2/* */
3/* z1parse.c */
4/* */
5/* Experimental Type 1 parser (body). */
6/* */
7/* Copyright 1996-2000 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 /*************************************************************************/
20 /* */
21 /* The Type 1 parser is in charge of the following: */
22 /* */
23 /* - provide an implementation of a growing sequence of objects called */
24 /* a `Z1_Table' (used to build various tables needed by the loader). */
25 /* */
26 /* - opening .pfb and .pfa files to extract their top-level and private */
27 /* dictionaries. */
28 /* */
29 /* - read numbers, arrays & strings from any dictionary. */
30 /* */
31 /* See `z1load.c' to see how data is loaded from the font file. */
32 /* */
33 /*************************************************************************/
34
35
36#include <freetype/internal/ftdebug.h>
37#include <freetype/internal/ftcalc.h>
38#include <freetype/internal/ftobjs.h>
39#include <freetype/internal/ftstream.h>
40#include <freetype/internal/t1errors.h>
41
42
43#ifdef FT_FLAT_COMPILE
44
45#include "z1parse.h"
46
47#else
48
49#include <type1z/z1parse.h>
50
51#endif
52
53
54#include <string.h> /* for strncmp() */
55
56
57 /*************************************************************************/
58 /* */
59 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
60 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
61 /* messages during execution. */
62 /* */
63#undef FT_COMPONENT
64#define FT_COMPONENT trace_z1parse
65
66
67 /*************************************************************************/
68 /*************************************************************************/
69 /*************************************************************************/
70 /***** *****/
71 /***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/
72 /***** *****/
73 /*************************************************************************/
74 /*************************************************************************/
75 /*************************************************************************/
76
77
78 /*************************************************************************/
79 /* */
80 /* <Function> */
81 /* Z1_New_Table */
82 /* */
83 /* <Description> */
84 /* Initialises a Z1_Table. */
85 /* */
86 /* <InOut> */
87 /* table :: The address of the target table. */
88 /* */
89 /* <Input> */
90 /* count :: The table size = the maximum number of elements. */
91 /* */
92 /* memory :: The memory object to use for all subsequent */
93 /* reallocations. */
94 /* */
95 /* <Return> */
96 /* FreeType error code. 0 means success. */
97 /* */
98 LOCAL_FUNC
99 FT_Error Z1_New_Table( Z1_Table* table,
100 FT_Int count,
101 FT_Memory memory )
102 {
103 FT_Error error;
104
105
106 table->memory = memory;
107 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
108 ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
109 goto Exit;
110
111 table->max_elems = count;
112 table->init = 0xdeadbeef;
113 table->num_elems = 0;
114 table->block = 0;
115 table->capacity = 0;
116 table->cursor = 0;
117
118 Exit:
119 if ( error )
120 FREE( table->elements );
121
122 return error;
123 }
124
125
126 static
127 void shift_elements( Z1_Table* table,
128 FT_Byte* old_base )
129 {
130 FT_Long delta = table->block - old_base;
131 FT_Byte** offset = table->elements;
132 FT_Byte** limit = offset + table->max_elems;
133
134
135 if ( delta )
136 for ( ; offset < limit; offset++ )
137 {
138 if ( offset[0] )
139 offset[0] += delta;
140 }
141 }
142
143
144 static
145 FT_Error reallocate_t1_table( Z1_Table* table,
146 FT_Int new_size )
147 {
148 FT_Memory memory = table->memory;
149 FT_Byte* old_base = table->block;
150 FT_Error error;
151
152
153 /* reallocate the base block */
154 if ( REALLOC( table->block, table->capacity, new_size ) )
155 return error;
156
157 table->capacity = new_size;
158
159 /* shift all offsets if necessary */
160 if ( old_base )
161 shift_elements( table, old_base );
162
163 return T1_Err_Ok;
164 }
165
166
167 /*************************************************************************/
168 /* */
169 /* <Function> */
170 /* Z1_Add_Table */
171 /* */
172 /* <Description> */
173 /* Adds an object to a Z1_Table, possibly growing its memory block. */
174 /* */
175 /* <InOut> */
176 /* table :: The target table. */
177 /* */
178 /* <Input> */
179 /* index :: The index of the object in the table. */
180 /* */
181 /* object :: The address of the object to copy in memory. */
182 /* */
183 /* length :: The length in bytes of the source object. */
184 /* */
185 /* <Return> */
186 /* FreeType error code. 0 means success. An error is returned if a */
187 /* reallocation fails. */
188 /* */
189 LOCAL_FUNC
190 FT_Error Z1_Add_Table( Z1_Table* table,
191 FT_Int index,
192 void* object,
193 FT_Int length )
194 {
195 if ( index < 0 || index > table->max_elems )
196 {
197 FT_ERROR(( "Z1_Add_Table: invalid index\n" ));
198 return T1_Err_Syntax_Error;
199 }
200
201 /* grow the base block if needed */
202 if ( table->cursor + length > table->capacity )
203 {
204 FT_Error error;
205 FT_Int new_size = table->capacity;
206
207
208 while ( new_size < table->cursor + length )
209 new_size += 1024;
210
211 error = reallocate_t1_table( table, new_size );
212 if ( error )
213 return error;
214 }
215
216 /* add the object to the base block and adjust offset */
217 table->elements[index] = table->block + table->cursor;
218 table->lengths [index] = length;
219 MEM_Copy( table->block + table->cursor, object, length );
220
221 table->cursor += length;
222 return T1_Err_Ok;
223 }
224
225
226#if 0
227
228 /*************************************************************************/
229 /* */
230 /* <Function> */
231 /* Z1_Done_Table */
232 /* */
233 /* <Description> */
234 /* Finalizes a Z1_Table (i.e., reallocate it to its current cursor). */
235 /* */
236 /* <InOut> */
237 /* table :: The target table. */
238 /* */
239 /* <Note> */
240 /* This function does NOT release the heap's memory block. It is up */
241 /* to the caller to clean it, or reference it in its own structures. */
242 /* */
243 LOCAL_FUNC
244 void Z1_Done_Table( Z1_Table* table )
245 {
246 FT_Memory memory = table->memory;
247 FT_Error error;
248 FT_Byte* old_base;
249
250
251 /* should never fail, as rec.cursor <= rec.size */
252 old_base = table->block;
253 if ( !old_base )
254 return;
255
256 (void)REALLOC( table->block, table->capacity, table->cursor );
257 table->capacity = table->cursor;
258
259 if ( old_base != table->block )
260 shift_elements( table, old_base );
261 }
262
263#endif /* 0 */
264
265
266 LOCAL_FUNC
267 void Z1_Release_Table( Z1_Table* table )
268 {
269 FT_Memory memory = table->memory;
270
271
272 if ( table->init == (FT_Long)0xDEADBEEF )
273 {
274 FREE( table->block );
275 FREE( table->elements );
276 FREE( table->lengths );
277 table->init = 0;
278 }
279 }
280
281
282 /*************************************************************************/
283 /*************************************************************************/
284 /*************************************************************************/
285 /***** *****/
286 /***** INPUT STREAM PARSER *****/
287 /***** *****/
288 /*************************************************************************/
289 /*************************************************************************/
290 /*************************************************************************/
291
292
293#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
294#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
295
296#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
297
298
299 LOCAL_FUNC
300 void Z1_Skip_Spaces( Z1_Parser* parser )
301 {
302 FT_Byte* cur = parser->cursor;
303 FT_Byte* limit = parser->limit;
304
305
306 while ( cur < limit )
307 {
308 FT_Byte c = *cur;
309
310
311 if ( !IS_Z1_SPACE( c ) )
312 break;
313 cur++;
314 }
315 parser->cursor = cur;
316 }
317
318
319 LOCAL_FUNC
320 void Z1_ToToken( Z1_Parser* parser,
321 Z1_Token_Rec* token )
322 {
323 FT_Byte* cur;
324 FT_Byte* limit;
325 FT_Byte starter, ender;
326 FT_Int embed;
327
328
329 token->type = t1_token_none;
330 token->start = 0;
331 token->limit = 0;
332
333 /* first of all, skip space */
334 Z1_Skip_Spaces( parser );
335
336 cur = parser->cursor;
337 limit = parser->limit;
338
339 if ( cur < limit )
340 {
341 switch ( *cur )
342 {
343 /************* check for strings ***********************/
344 case '(':
345 token->type = t1_token_string;
346 ender = ')';
347 goto Lookup_Ender;
348
349 /************* check for programs/array ****************/
350 case '{':
351 token->type = t1_token_array;
352 ender = '}';
353 goto Lookup_Ender;
354
355 /************* check for table/array ******************/
356 case '[':
357 token->type = t1_token_array;
358 ender = ']';
359
360 Lookup_Ender:
361 embed = 1;
362 starter = *cur++;
363 token->start = cur;
364 while ( cur < limit )
365 {
366 if ( *cur == starter )
367 embed++;
368 else if ( *cur == ender )
369 {
370 embed--;
371 if ( embed <= 0 )
372 {
373 token->limit = cur++;
374 break;
375 }
376 }
377 cur++;
378 }
379 break;
380
381 /* **************** otherwise, it's any token **********/
382 default:
383 token->start = cur++;
384 token->type = t1_token_any;
385 while ( cur < limit && !IS_Z1_SPACE( *cur ) )
386 cur++;
387
388 token->limit = cur;
389 }
390
391 if ( !token->limit )
392 {
393 token->start = 0;
394 token->type = t1_token_none;
395 }
396
397 parser->cursor = cur;
398 }
399 }
400
401
402 LOCAL_FUNC
403 void Z1_ToTokenArray( Z1_Parser* parser,
404 Z1_Token_Rec* tokens,
405 FT_UInt max_tokens,
406 FT_Int* pnum_tokens )
407 {
408 Z1_Token_Rec master;
409
410
411 *pnum_tokens = -1;
412
413 Z1_ToToken( parser, &master );
414 if ( master.type == t1_token_array )
415 {
416 FT_Byte* old_cursor = parser->cursor;
417 FT_Byte* old_limit = parser->limit;
418 Z1_Token_Rec* cur = tokens;
419 Z1_Token_Rec* limit = cur + max_tokens;
420
421
422 parser->cursor = master.start;
423 parser->limit = master.limit;
424
425 while ( parser->cursor < parser->limit )
426 {
427 Z1_Token_Rec token;
428
429
430 Z1_ToToken( parser, &token );
431 if ( !token.type )
432 break;
433
434 if ( cur < limit )
435 *cur = token;
436
437 cur++;
438 }
439
440 *pnum_tokens = cur - tokens;
441
442 parser->cursor = old_cursor;
443 parser->limit = old_limit;
444 }
445 }
446
447
448 static
449 FT_Long t1_toint( FT_Byte** cursor,
450 FT_Byte* limit )
451 {
452 FT_Long result = 0;
453 FT_Byte* cur = *cursor;
454 FT_Byte c, d;
455
456
457 for ( ; cur < limit; cur++ )
458 {
459 c = *cur;
460 d = (FT_Byte)( c - '0' );
461 if ( d < 10 )
462 break;
463
464 if ( c == '-' )
465 {
466 cur++;
467 break;
468 }
469 }
470
471 if ( cur < limit )
472 {
473 do
474 {
475 d = (FT_Byte)( cur[0] - '0' );
476 if ( d >= 10 )
477 break;
478
479 result = result * 10 + d;
480 cur++;
481
482 } while ( cur < limit );
483
484 if ( c == '-' )
485 result = -result;
486 }
487
488 *cursor = cur;
489 return result;
490 }
491
492
493 static
494 FT_Long t1_tofixed( FT_Byte** cursor,
495 FT_Byte* limit,
496 FT_Long power_ten )
497 {
498 FT_Byte* cur = *cursor;
499 FT_Long num, divider, result;
500 FT_Int sign = 0;
501 FT_Byte d;
502
503
504 if ( cur >= limit )
505 return 0;
506
507 /* first of all, read the integer part */
508 result = t1_toint( &cur, limit ) << 16;
509 num = 0;
510 divider = 1;
511
512 if ( result < 0 )
513 {
514 sign = 1;
515 result = -result;
516 }
517
518 if ( cur >= limit )
519 goto Exit;
520
521 /* read decimal part, if any */
522 if ( *cur == '.' && cur + 1 < limit )
523 {
524 cur++;
525
526 for (;;)
527 {
528 d = (FT_Byte)( *cur - '0' );
529 if ( d >= 10 )
530 break;
531
532 if ( divider < 10000000L )
533 {
534 num = num * 10 + d;
535 divider *= 10;
536 }
537
538 cur++;
539 if ( cur >= limit )
540 break;
541 }
542 }
543
544 /* read exponent, if any */
545 if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
546 {
547 cur++;
548 power_ten += t1_toint( &cur, limit );
549 }
550
551 Exit:
552 /* raise to power of ten if needed */
553 while ( power_ten > 0 )
554 {
555 result = result * 10;
556 num = num * 10;
557 power_ten--;
558 }
559
560 while ( power_ten < 0 )
561 {
562 result = result / 10;
563 divider = divider * 10;
564 power_ten++;
565 }
566
567 if ( num )
568 result += FT_DivFix( num, divider );
569
570 if ( sign )
571 result = -result;
572
573 *cursor = cur;
574 return result;
575 }
576
577
578 static
579 FT_Int t1_tocoordarray( FT_Byte** cursor,
580 FT_Byte* limit,
581 FT_Int max_coords,
582 FT_Short* coords )
583 {
584 FT_Byte* cur = *cursor;
585 FT_Int count = 0;
586 FT_Byte c, ender;
587
588
589 if ( cur >= limit )
590 goto Exit;
591
592 /* check for the beginning of an array. If not, only one number will */
593 /* be read */
594 c = *cur;
595 ender = 0;
596
597 if ( c == '[' )
598 ender = ']';
599
600 if ( c == '{' )
601 ender = '}';
602
603 if ( ender )
604 cur++;
605
606 /* now, read the coordinates */
607 for ( ; cur < limit; )
608 {
609 /* skip whitespace in front of data */
610 for (;;)
611 {
612 c = *cur;
613 if ( c != ' ' && c != '\t' )
614 break;
615
616 cur++;
617 if ( cur >= limit )
618 goto Exit;
619 }
620
621 if ( count >= max_coords || c == ender )
622 break;
623
624 coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
625 count++;
626
627 if ( !ender )
628 break;
629 }
630
631 Exit:
632 *cursor = cur;
633 return count;
634 }
635
636
637 static
638 FT_Int t1_tofixedarray( FT_Byte** cursor,
639 FT_Byte* limit,
640 FT_Int max_values,
641 FT_Fixed* values,
642 FT_Int power_ten )
643 {
644 FT_Byte* cur = *cursor;
645 FT_Int count = 0;
646 FT_Byte c, ender;
647
648
649 if ( cur >= limit ) goto Exit;
650
651 /* check for the beginning of an array. If not, only one number will */
652 /* be read */
653 c = *cur;
654 ender = 0;
655
656 if ( c == '[' )
657 ender = ']';
658
659 if ( c == '{' )
660 ender = '}';
661
662 if ( ender )
663 cur++;
664
665 /* now, read the values */
666 for ( ; cur < limit; )
667 {
668 /* skip whitespace in front of data */
669 for (;;)
670 {
671 c = *cur;
672 if ( c != ' ' && c != '\t' )
673 break;
674
675 cur++;
676 if ( cur >= limit )
677 goto Exit;
678 }
679
680 if ( count >= max_values || c == ender )
681 break;
682
683 values[count] = t1_tofixed( &cur, limit, power_ten );
684 count++;
685
686 if ( !ender )
687 break;
688 }
689
690 Exit:
691 *cursor = cur;
692 return count;
693 }
694
695
696#if 0
697
698 static
699 FT_String* t1_tostring( FT_Byte** cursor,
700 FT_Byte* limit,
701 FT_Memory memory )
702 {
703 FT_Byte* cur = *cursor;
704 FT_Int len = 0;
705 FT_Int count;
706 FT_String* result;
707 FT_Error error;
708
709
710 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
711 /* that simply doesn't begin with an opening parenthesis, even */
712 /* though they have a closing one! E.g. "amuncial.pfb" */
713 /* */
714 /* We must deal with these ill-fated cases there. Note that */
715 /* these fonts didn't work with the old Type 1 driver as the */
716 /* notice/copyright was not recognized as a valid string token */
717 /* and made the old token parser commit errors. */
718
719 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
720 cur++;
721 if ( cur + 1 >= limit )
722 return 0;
723
724 if ( *cur == '(' )
725 cur++; /* skip the opening parenthesis, if there is one */
726
727 *cursor = cur;
728 count = 0;
729
730 /* then, count its length */
731 for ( ; cur < limit; cur++ )
732 {
733 if ( *cur == '(' )
734 count++;
735
736 else if ( *cur == ')' )
737 {
738 count--;
739 if ( count < 0 )
740 break;
741 }
742 }
743
744 len = cur - *cursor;
745 if ( cur >= limit || ALLOC( result, len + 1 ) )
746 return 0;
747
748 /* now copy the string */
749 MEM_Copy( result, *cursor, len );
750 result[len] = '\0';
751 *cursor = cur;
752 return result;
753 }
754
755#endif /* 0 */
756
757
758 static
759 int t1_tobool( FT_Byte** cursor,
760 FT_Byte* limit )
761 {
762 FT_Byte* cur = *cursor;
763 FT_Bool result = 0;
764
765
766 /* return 1 if we find `true', 0 otherwise */
767 if ( cur + 3 < limit &&
768 cur[0] == 't' &&
769 cur[1] == 'r' &&
770 cur[2] == 'u' &&
771 cur[3] == 'e' )
772 {
773 result = 1;
774 cur += 5;
775 }
776 else if ( cur + 4 < limit &&
777 cur[0] == 'f' &&
778 cur[1] == 'a' &&
779 cur[2] == 'l' &&
780 cur[3] == 's' &&
781 cur[4] == 'e' )
782 {
783 result = 0;
784 cur += 6;
785 }
786
787 *cursor = cur;
788 return result;
789 }
790
791
792 /* Load a simple field (i.e. non-table) into the current list of objects */
793 LOCAL_FUNC
794 FT_Error Z1_Load_Field( Z1_Parser* parser,
795 const Z1_Field_Rec* field,
796 void** objects,
797 FT_UInt max_objects,
798 FT_ULong* pflags )
799 {
800 Z1_Token_Rec token;
801 FT_Byte* cur;
802 FT_Byte* limit;
803 FT_UInt count;
804 FT_UInt index;
805 FT_Error error;
806
807
808 Z1_ToToken( parser, &token );
809 if ( !token.type )
810 goto Fail;
811
812 count = 1;
813 index = 0;
814 cur = token.start;
815 limit = token.limit;
816
817 if ( token.type == t1_token_array )
818 {
819 /* if this is an array, and we have no blend, an error occurs */
820 if ( max_objects == 0 )
821 goto Fail;
822
823 count = max_objects;
824 index = 1;
825 }
826
827 for ( ; count > 0; count--, index++ )
828 {
829 FT_Byte* q = (FT_Byte*)objects[index] + field->offset;
830 FT_Long val;
831 FT_String* string;
832
833 switch ( field->type )
834 {
835 case t1_field_bool:
836 val = t1_tobool( &cur, limit );
837 goto Store_Integer;
838
839 case t1_field_fixed:
840 val = t1_tofixed( &cur, limit, 3 );
841 goto Store_Integer;
842
843 case t1_field_integer:
844 val = t1_toint( &cur, limit );
845
846 Store_Integer:
847 switch ( field->size )
848 {
849 case 1:
850 *(FT_Byte*)q = (FT_Byte)val;
851 break;
852
853 case 2:
854 *(FT_UShort*)q = (FT_UShort)val;
855 break;
856
857 case 4:
858 *(FT_UInt32*)q = (FT_UInt32)val;
859 break;
860
861 default: /* for 64-bit systems */
862 *(FT_Long*)q = val;
863 }
864 break;
865
866 case t1_field_string:
867 {
868 FT_Memory memory = parser->memory;
869 FT_UInt len = limit-cur;
870
871 if ( ALLOC( string, len + 1 ) )
872 goto Exit;
873
874 MEM_Copy( string, cur, len );
875 string[len] = 0;
876
877 *(FT_String**)q = string;
878 }
879 break;
880
881 default:
882 /* an error occured */
883 goto Fail;
884 }
885 }
886
887 if ( pflags )
888 *pflags |= 1L << field->flag_bit;
889
890 error = FT_Err_Ok;
891
892 Exit:
893 return error;
894
895 Fail:
896 error = T1_Err_Invalid_File_Format;
897 goto Exit;
898 }
899
900
901#define T1_MAX_TABLE_ELEMENTS 32
902
903
904 LOCAL_FUNC
905 FT_Error Z1_Load_Field_Table( Z1_Parser* parser,
906 const Z1_Field_Rec* field,
907 void** objects,
908 FT_UInt max_objects,
909 FT_ULong* pflags )
910 {
911 Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
912 Z1_Token_Rec* token;
913 FT_Int num_elements;
914 FT_Error error = 0;
915 FT_Byte* old_cursor;
916 FT_Byte* old_limit;
917 Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field;
918
919
920 Z1_ToTokenArray( parser, elements, 32, &num_elements );
921 if ( num_elements < 0 )
922 goto Fail;
923
924 if ( num_elements > T1_MAX_TABLE_ELEMENTS )
925 num_elements = T1_MAX_TABLE_ELEMENTS;
926
927 old_cursor = parser->cursor;
928 old_limit = parser->limit;
929
930 /* we store the elements count */
931 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = num_elements;
932
933 /* we now load each element, adjusting the field.offset on each one */
934 token = elements;
935 for ( ; num_elements > 0; num_elements--, token++ )
936 {
937 parser->cursor = token->start;
938 parser->limit = token->limit;
939 Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
940 fieldrec.offset += fieldrec.size;
941 }
942
943 if ( pflags )
944 *pflags |= 1L << field->flag_bit;
945
946 parser->cursor = old_cursor;
947 parser->limit = old_limit;
948
949 Exit:
950 return error;
951
952 Fail:
953 error = T1_Err_Invalid_File_Format;
954 goto Exit;
955 }
956
957
958 LOCAL_FUNC
959 FT_Long Z1_ToInt ( Z1_Parser* parser )
960 {
961 return t1_toint( &parser->cursor, parser->limit );
962 }
963
964
965 LOCAL_FUNC
966 FT_Long Z1_ToFixed( Z1_Parser* parser,
967 FT_Int power_ten )
968 {
969 return t1_tofixed( &parser->cursor, parser->limit, power_ten );
970 }
971
972
973 LOCAL_FUNC
974 FT_Int Z1_ToCoordArray( Z1_Parser* parser,
975 FT_Int max_coords,
976 FT_Short* coords )
977 {
978 return t1_tocoordarray( &parser->cursor, parser->limit,
979 max_coords, coords );
980 }
981
982
983 LOCAL_FUNC
984 FT_Int Z1_ToFixedArray( Z1_Parser* parser,
985 FT_Int max_values,
986 FT_Fixed* values,
987 FT_Int power_ten )
988 {
989 return t1_tofixedarray( &parser->cursor, parser->limit,
990 max_values, values, power_ten );
991 }
992
993
994#if 0
995
996 LOCAL_FUNC
997 FT_String* Z1_ToString( Z1_Parser* parser )
998 {
999 return t1_tostring( &parser->cursor, parser->limit, parser->memory );
1000 }
1001
1002
1003 LOCAL_FUNC
1004 FT_Bool Z1_ToBool( Z1_Parser* parser )
1005 {
1006 return t1_tobool( &parser->cursor, parser->limit );
1007 }
1008
1009#endif /* 0 */
1010
1011
1012 static
1013 FT_Error read_pfb_tag( FT_Stream stream,
1014 FT_UShort* tag,
1015 FT_Long* size )
1016 {
1017 FT_Error error;
1018
1019
1020 if ( READ_UShort( *tag ) )
1021 goto Exit;
1022
1023 if ( *tag == 0x8001 || *tag == 0x8002 )
1024 {
1025 FT_Long asize;
1026
1027
1028 if ( READ_ULong( asize ) )
1029 goto Exit;
1030
1031 /* swap between big and little endianness */
1032 *size = ( ( asize & 0xFF000000L ) >> 24 ) |
1033 ( ( asize & 0x00FF0000L ) >> 8 ) |
1034 ( ( asize & 0x0000FF00L ) << 8 ) |
1035 ( ( asize & 0x000000FFL ) << 24 );
1036 }
1037
1038 Exit:
1039 return error;
1040 }
1041
1042
1043 LOCAL_FUNC
1044 FT_Error Z1_New_Parser( Z1_Parser* parser,
1045 FT_Stream stream,
1046 FT_Memory memory )
1047 {
1048 FT_Error error;
1049 FT_UShort tag;
1050 FT_Long size;
1051
1052
1053 parser->stream = stream;
1054 parser->memory = memory;
1055 parser->base_len = 0;
1056 parser->base_dict = 0;
1057 parser->private_len = 0;
1058 parser->private_dict = 0;
1059 parser->in_pfb = 0;
1060 parser->in_memory = 0;
1061 parser->single_block = 0;
1062
1063 parser->cursor = 0;
1064 parser->limit = 0;
1065
1066 /******************************************************************/
1067 /* */
1068 /* Here a short summary of what is going on: */
1069 /* */
1070 /* When creating a new Type 1 parser, we try to locate and load */
1071 /* the base dictionary if this is possible (i.e. for PFB */
1072 /* files). Otherwise, we load the whole font into memory. */
1073 /* */
1074 /* When `loading' the base dictionary, we only setup pointers */
1075 /* in the case of a memory-based stream. Otherwise, we */
1076 /* allocate and load the base dictionary in it. */
1077 /* */
1078 /* parser->in_pfb is set if we are in a binary (".pfb") font. */
1079 /* parser->in_memory is set if we have a memory stream. */
1080 /* */
1081
1082 /* try to compute the size of the base dictionary; */
1083 /* look for a Postscript binary file tag, i.e 0x8001 */
1084 if ( FILE_Seek( 0L ) )
1085 goto Exit;
1086
1087 error = read_pfb_tag( stream, &tag, &size );
1088 if ( error )
1089 goto Exit;
1090
1091 if ( tag != 0x8001 )
1092 {
1093 /* assume that this is a PFA file for now; an error will */
1094 /* be produced later when more things are checked */
1095 (void)FILE_Seek( 0L );
1096 size = stream->size;
1097 }
1098 else
1099 parser->in_pfb = 1;
1100
1101 /* now, try to load `size' bytes of the `base' dictionary we */
1102 /* found previously */
1103
1104 /* if it is a memory-based resource, set up pointers */
1105 if ( !stream->read )
1106 {
1107 parser->base_dict = (FT_Byte*)stream->base + stream->pos;
1108 parser->base_len = size;
1109 parser->in_memory = 1;
1110
1111 /* check that the `size' field is valid */
1112 if ( FILE_Skip( size ) )
1113 goto Exit;
1114 }
1115 else
1116 {
1117 /* read segment in memory */
1118 if ( ALLOC( parser->base_dict, size ) ||
1119 FILE_Read( parser->base_dict, size ) )
1120 goto Exit;
1121 parser->base_len = size;
1122 }
1123
1124 /* Now check font format; we must see `%!PS-AdobeFont-1' */
1125 /* or `%!FontType' */
1126 {
1127 if ( size <= 16 ||
1128 ( strncmp( (const char*)parser->base_dict,
1129 "%!PS-AdobeFont-1", 16 ) &&
1130 strncmp( (const char*)parser->base_dict,
1131 "%!FontType", 10 ) ) )
1132 {
1133 FT_TRACE2(( "[not a Type1 font]\n" ));
1134 error = FT_Err_Unknown_File_Format;
1135 }
1136 else
1137 {
1138 parser->cursor = parser->base_dict;
1139 parser->limit = parser->cursor + parser->base_len;
1140 }
1141 }
1142
1143 Exit:
1144 if ( error && !parser->in_memory )
1145 FREE( parser->base_dict );
1146
1147 return error;
1148 }
1149
1150
1151 LOCAL_FUNC
1152 void Z1_Done_Parser( Z1_Parser* parser )
1153 {
1154 FT_Memory memory = parser->memory;
1155
1156
1157 /* always free the private dictionary */
1158 FREE( parser->private_dict );
1159
1160 /* free the base dictionary only when we have a disk stream */
1161 if ( !parser->in_memory )
1162 FREE( parser->base_dict );
1163 }
1164
1165
1166 /* return the value of an hexadecimal digit */
1167 static
1168 int hexa_value( char c )
1169 {
1170 unsigned int d;
1171
1172
1173 d = (unsigned int)( c - '0' );
1174 if ( d <= 9 )
1175 return (int)d;
1176
1177 d = (unsigned int)( c - 'a' );
1178 if ( d <= 5 )
1179 return (int)( d + 10 );
1180
1181 d = (unsigned int)( c - 'A' );
1182 if ( d <= 5 )
1183 return (int)( d + 10 );
1184
1185 return -1;
1186 }
1187
1188
1189 LOCAL_FUNC
1190 void Z1_Decrypt( FT_Byte* buffer,
1191 FT_Int length,
1192 FT_UShort seed )
1193 {
1194 while ( length > 0 )
1195 {
1196 FT_Byte plain;
1197
1198
1199 plain = ( *buffer ^ ( seed >> 8 ) );
1200 seed = ( *buffer + seed ) * 52845 + 22719;
1201 *buffer++ = plain;
1202 length--;
1203 }
1204 }
1205
1206
1207 LOCAL_FUNC
1208 FT_Error Z1_Get_Private_Dict( Z1_Parser* parser )
1209 {
1210 FT_Stream stream = parser->stream;
1211 FT_Memory memory = parser->memory;
1212 FT_Error error = 0;
1213 FT_Long size;
1214
1215
1216 if ( parser->in_pfb )
1217 {
1218 /* in the case of the PFB format, the private dictionary can be */
1219 /* made of several segments. We thus first read the number of */
1220 /* segments to compute the total size of the private dictionary */
1221 /* then re-read them into memory. */
1222 FT_Long start_pos = FILE_Pos();
1223 FT_UShort tag;
1224 FT_Long size;
1225
1226
1227 parser->private_len = 0;
1228 for (;;)
1229 {
1230 error = read_pfb_tag( stream, &tag, &size );
1231 if ( error )
1232 goto Fail;
1233
1234 if ( tag != 0x8002 )
1235 break;
1236
1237 parser->private_len += size;
1238
1239 if ( FILE_Skip( size ) )
1240 goto Fail;
1241 }
1242
1243 /* Check that we have a private dictionary there */
1244 /* and allocate private dictionary buffer */
1245 if ( parser->private_len == 0 )
1246 {
1247 FT_ERROR(( "Z1_Get_Private_Dict:" ));
1248 FT_ERROR(( " invalid private dictionary section\n" ));
1249 error = T1_Err_Invalid_File_Format;
1250 goto Fail;
1251 }
1252
1253 if ( FILE_Seek( start_pos ) ||
1254 ALLOC( parser->private_dict, parser->private_len ) )
1255 goto Fail;
1256
1257 parser->private_len = 0;
1258 for (;;)
1259 {
1260 error = read_pfb_tag( stream, &tag, &size );
1261 if ( error || tag != 0x8002 )
1262 {
1263 error = FT_Err_Ok;
1264 break;
1265 }
1266
1267 if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
1268 goto Fail;
1269
1270 parser->private_len += size;
1271 }
1272 }
1273 else
1274 {
1275 /* we have already `loaded' the whole PFA font file into memory; */
1276 /* if this is a memory resource, allocate a new block to hold */
1277 /* the private dict. Otherwise, simply overwrite into the base */
1278 /* dictionary block in the heap. */
1279
1280 /* first of all, look at the `eexec' keyword */
1281 FT_Byte* cur = parser->base_dict;
1282 FT_Byte* limit = cur + parser->base_len;
1283 FT_Byte c;
1284
1285
1286 for (;;)
1287 {
1288 c = cur[0];
1289 if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
1290 /* newline + 4 chars */
1291 {
1292 if ( cur[1] == 'e' && cur[2] == 'x' &&
1293 cur[3] == 'e' && cur[4] == 'c' )
1294 {
1295 cur += 6; /* we skip the newling after the `eexec' */
1296
1297 /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
1298 /* skip the extra \n if we find it */
1299 if ( cur[0] == '\n' )
1300 cur++;
1301
1302 break;
1303 }
1304 }
1305 cur++;
1306 if ( cur >= limit )
1307 {
1308 FT_ERROR(( "Z1_Get_Private_Dict:" ));
1309 FT_ERROR(( " could not find `eexec' keyword\n" ));
1310 error = T1_Err_Invalid_File_Format;
1311 goto Exit;
1312 }
1313 }
1314
1315 /* now determine where to write the _encrypted_ binary private */
1316 /* dictionary. We overwrite the base dictionary for disk-based */
1317 /* resources and allocate a new block otherwise */
1318
1319 size = parser->base_len - ( cur - parser->base_dict);
1320
1321 if ( parser->in_memory )
1322 {
1323 /* note that we allocate one more byte to put a terminating `0' */
1324 if ( ALLOC( parser->private_dict, size + 1 ) )
1325 goto Fail;
1326 parser->private_len = size;
1327 }
1328 else
1329 {
1330 parser->single_block = 1;
1331 parser->private_dict = parser->base_dict;
1332 parser->private_len = size;
1333 parser->base_dict = 0;
1334 parser->base_len = 0;
1335 }
1336
1337 /* now determine whether the private dictionary is encoded in binary */
1338 /* or hexadecimal ASCII format -- decode it accordingly */
1339
1340 /* we need to access the next 4 bytes (after the final \r following */
1341 /* the `eexec' keyword); if they all are hexadecimal digits, then */
1342 /* we have a case of ASCII storage */
1343
1344 if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
1345 hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
1346
1347 /* binary encoding -- `simply' copy the private dict */
1348 MEM_Copy( parser->private_dict, cur, size );
1349
1350 else
1351 {
1352 /* ASCII hexadecimal encoding */
1353
1354 FT_Byte* write;
1355 FT_Int count;
1356
1357
1358 write = parser->private_dict;
1359 count = 0;
1360
1361 for ( ;cur < limit; cur++ )
1362 {
1363 int hex1;
1364
1365
1366 /* check for newline */
1367 if ( cur[0] == '\r' || cur[0] == '\n' )
1368 continue;
1369
1370 /* exit if we have a non-hexadecimal digit that isn't a newline */
1371 hex1 = hexa_value( cur[0] );
1372 if ( hex1 < 0 || cur + 1 >= limit )
1373 break;
1374
1375 /* otherwise, store byte */
1376 *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
1377 count++;
1378 cur++;
1379 }
1380
1381 /* put a safeguard */
1382 parser->private_len = write - parser->private_dict;
1383 *write++ = 0;
1384 }
1385 }
1386
1387 /* we now decrypt the encoded binary private dictionary */
1388 Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
1389 parser->cursor = parser->private_dict;
1390 parser->limit = parser->cursor + parser->private_len;
1391
1392 Fail:
1393 Exit:
1394 return error;
1395 }
1396
1397
1398/* END */