]>
Commit | Line | Data |
---|---|---|
cabec872 RR |
1 | /***************************************************************************/ |
2 | /* */ | |
3 | /* cidparse.c */ | |
4 | /* */ | |
5 | /* CID-keyed Type1 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 | #include <freetype/internal/ftdebug.h> | |
20 | #include <freetype/internal/ftcalc.h> | |
21 | #include <freetype/internal/ftobjs.h> | |
22 | #include <freetype/internal/ftstream.h> | |
23 | #include <freetype/internal/t1errors.h> | |
24 | ||
25 | ||
26 | #ifdef FT_FLAT_COMPILE | |
27 | ||
28 | #include "cidparse.h" | |
29 | ||
30 | #else | |
31 | ||
32 | #include <cid/cidparse.h> | |
33 | ||
34 | #endif | |
35 | ||
36 | ||
37 | #include <string.h> /* for strncmp() */ | |
38 | ||
39 | ||
40 | /*************************************************************************/ | |
41 | /* */ | |
42 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
43 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
44 | /* messages during execution. */ | |
45 | /* */ | |
46 | #undef FT_COMPONENT | |
47 | #define FT_COMPONENT trace_cidparse | |
48 | ||
49 | ||
50 | #if 0 | |
51 | ||
52 | /*************************************************************************/ | |
53 | /*************************************************************************/ | |
54 | /*************************************************************************/ | |
55 | /***** *****/ | |
56 | /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/ | |
57 | /***** *****/ | |
58 | /*************************************************************************/ | |
59 | /*************************************************************************/ | |
60 | /*************************************************************************/ | |
61 | ||
62 | ||
63 | /*************************************************************************/ | |
64 | /* */ | |
65 | /* <Function> */ | |
66 | /* CID_New_Table */ | |
67 | /* */ | |
68 | /* <Description> */ | |
69 | /* Initializes a CID_Table. */ | |
70 | /* */ | |
71 | /* <InOut> */ | |
72 | /* table :: The address of the target table. */ | |
73 | /* */ | |
74 | /* <Input> */ | |
75 | /* count :: The table size, i.e., the maximal number of elements. */ | |
76 | /* */ | |
77 | /* memory :: The memory object to be used for all subsequent */ | |
78 | /* reallocations. */ | |
79 | /* */ | |
80 | /* <Return> */ | |
81 | /* FreeType error code. 0 means success. */ | |
82 | /* */ | |
83 | LOCAL_FUNC | |
84 | FT_Error CID_New_Table( CID_Table* table, | |
85 | FT_Int count, | |
86 | FT_Memory memory ) | |
87 | { | |
88 | FT_Error error; | |
89 | ||
90 | ||
91 | table->memory = memory; | |
92 | if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) || | |
93 | ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) | |
94 | goto Exit; | |
95 | ||
96 | table->max_elems = count; | |
97 | table->init = 0xDEADBEEFL; | |
98 | table->num_elems = 0; | |
99 | table->block = 0; | |
100 | table->capacity = 0; | |
101 | table->cursor = 0; | |
102 | ||
103 | Exit: | |
104 | if ( error ) | |
105 | FREE( table->elements ); | |
106 | ||
107 | return error; | |
108 | } | |
109 | ||
110 | ||
111 | static | |
112 | void shift_elements( CID_Table* table, | |
113 | FT_Byte* old_base ) | |
114 | { | |
115 | FT_Long delta = table->block - old_base; | |
116 | FT_Byte** offset = table->elements; | |
117 | FT_Byte** limit = offset + table->max_elems; | |
118 | ||
119 | ||
120 | if ( delta ) | |
121 | for ( ; offset < limit; offset++ ) | |
122 | { | |
123 | if ( offset[0] ) | |
124 | offset[0] += delta; | |
125 | } | |
126 | } | |
127 | ||
128 | ||
129 | static | |
130 | FT_Error reallocate_t1_table( CID_Table* table, | |
131 | FT_Int new_size ) | |
132 | { | |
133 | FT_Memory memory = table->memory; | |
134 | FT_Byte* old_base = table->block; | |
135 | FT_Error error; | |
136 | ||
137 | ||
138 | /* realloc the base block */ | |
139 | if ( REALLOC( table->block, table->capacity, new_size ) ) | |
140 | return error; | |
141 | ||
142 | table->capacity = new_size; | |
143 | ||
144 | /* shift all offsets when needed */ | |
145 | if ( old_base ) | |
146 | shift_elements( table, old_base ); | |
147 | ||
148 | return T1_Err_Ok; | |
149 | } | |
150 | ||
151 | ||
152 | /*************************************************************************/ | |
153 | /* */ | |
154 | /* <Function> */ | |
155 | /* CID_Add_Table */ | |
156 | /* */ | |
157 | /* <Description> */ | |
158 | /* Adds an object to a CID_Table, possibly growing its memory block. */ | |
159 | /* */ | |
160 | /* <InOut> */ | |
161 | /* table :: The target table. */ | |
162 | /* */ | |
163 | /* <Input> */ | |
164 | /* index :: The index of the object in the table. */ | |
165 | /* */ | |
166 | /* object :: The address of the object to copy in the memory. */ | |
167 | /* */ | |
168 | /* length :: The length in bytes of the source object. */ | |
169 | /* */ | |
170 | /* <Return> */ | |
171 | /* FreeType error code. 0 means success. An error is returned if */ | |
172 | /* reallocation fails. */ | |
173 | /* */ | |
174 | LOCAL_FUNC | |
175 | FT_Error CID_Add_Table( CID_Table* table, | |
176 | FT_Int index, | |
177 | void* object, | |
178 | FT_Int length ) | |
179 | { | |
180 | if ( index < 0 || index > table->max_elems ) | |
181 | { | |
182 | FT_ERROR(( "CID_Add_Table: invalid index\n" )); | |
183 | return T1_Err_Syntax_Error; | |
184 | } | |
185 | ||
186 | /* grow the base block if needed */ | |
187 | if ( table->cursor + length > table->capacity ) | |
188 | { | |
189 | FT_Error error; | |
190 | FT_Int new_size = table->capacity; | |
191 | ||
192 | ||
193 | while ( new_size < table->cursor + length ) | |
194 | new_size += 1024; | |
195 | ||
196 | error = reallocate_t1_table( table, new_size ); | |
197 | if ( error ) | |
198 | return error; | |
199 | } | |
200 | ||
201 | /* add the object to the base block and adjust offset */ | |
202 | table->elements[index] = table->block + table->cursor; | |
203 | table->lengths [index] = length; | |
204 | ||
205 | MEM_Copy( table->block + table->cursor, object, length ); | |
206 | ||
207 | table->cursor += length; | |
208 | ||
209 | return T1_Err_Ok; | |
210 | } | |
211 | ||
212 | ||
213 | /*************************************************************************/ | |
214 | /* */ | |
215 | /* <Function> */ | |
216 | /* CID_Done_Table */ | |
217 | /* */ | |
218 | /* <Description> */ | |
219 | /* Finalizes a CID_Table (reallocate it to its current cursor). */ | |
220 | /* */ | |
221 | /* <InOut> */ | |
222 | /* table :: The target table. */ | |
223 | /* */ | |
224 | /* <Note> */ | |
225 | /* This function does NOT release the heap's memory block. It is up */ | |
226 | /* to the caller to clean it, or reference it in its own structures. */ | |
227 | /* */ | |
228 | LOCAL_FUNC | |
229 | void CID_Done_Table( CID_Table* table ) | |
230 | { | |
231 | FT_Memory memory = table->memory; | |
232 | FT_Error error; | |
233 | FT_Byte* old_base; | |
234 | ||
235 | ||
236 | /* should never fail, as rec.cursor <= rec.size */ | |
237 | old_base = table->block; | |
238 | if ( !old_base ) | |
239 | return; | |
240 | ||
241 | (void)REALLOC( table->block, table->capacity, table->cursor ); | |
242 | table->capacity = table->cursor; | |
243 | ||
244 | if ( old_base != table->block ) | |
245 | shift_elements( table, old_base ); | |
246 | } | |
247 | ||
248 | ||
249 | LOCAL_FUNC | |
250 | void CID_Release_Table( CID_Table* table ) | |
251 | { | |
252 | FT_Memory memory = table->memory; | |
253 | ||
254 | ||
255 | if ( table->init == 0xDEADBEEFL ) | |
256 | { | |
257 | FREE( table->block ); | |
258 | FREE( table->elements ); | |
259 | FREE( table->lengths ); | |
260 | table->init = 0; | |
261 | } | |
262 | } | |
263 | ||
264 | #endif /* 0 */ | |
265 | ||
266 | ||
267 | /*************************************************************************/ | |
268 | /*************************************************************************/ | |
269 | /*************************************************************************/ | |
270 | /***** *****/ | |
271 | /***** INPUT STREAM PARSER *****/ | |
272 | /***** *****/ | |
273 | /*************************************************************************/ | |
274 | /*************************************************************************/ | |
275 | /*************************************************************************/ | |
276 | ||
277 | ||
278 | #define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' ) | |
279 | #define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' ) | |
280 | ||
281 | #define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) ) | |
282 | ||
283 | ||
284 | LOCAL_FUNC | |
285 | void CID_Skip_Spaces( CID_Parser* parser ) | |
286 | { | |
287 | FT_Byte* cur = parser->cursor; | |
288 | FT_Byte* limit = parser->limit; | |
289 | ||
290 | ||
291 | while ( cur < limit ) | |
292 | { | |
293 | FT_Byte c = *cur; | |
294 | ||
295 | ||
296 | if ( !IS_CID_SPACE( c ) ) | |
297 | break; | |
298 | cur++; | |
299 | } | |
300 | ||
301 | parser->cursor = cur; | |
302 | } | |
303 | ||
304 | ||
305 | LOCAL_FUNC | |
306 | void CID_ToToken( CID_Parser* parser, | |
307 | CID_Token_Rec* token ) | |
308 | { | |
309 | FT_Byte* cur; | |
310 | FT_Byte* limit; | |
311 | FT_Byte starter, ender; | |
312 | FT_Int embed; | |
313 | ||
314 | ||
315 | token->type = t1_token_none; | |
316 | token->start = 0; | |
317 | token->limit = 0; | |
318 | ||
319 | /* first of all, skip space */ | |
320 | CID_Skip_Spaces( parser ); | |
321 | ||
322 | cur = parser->cursor; | |
323 | limit = parser->limit; | |
324 | ||
325 | if ( cur < limit ) | |
326 | { | |
327 | switch ( *cur ) | |
328 | { | |
329 | /************* check for strings ***********************/ | |
330 | case '(': | |
331 | token->type = t1_token_string; | |
332 | ender = ')'; | |
333 | goto Lookup_Ender; | |
334 | ||
335 | /************* check for programs/array ****************/ | |
336 | case '{': | |
337 | token->type = t1_token_array; | |
338 | ender = '}'; | |
339 | goto Lookup_Ender; | |
340 | ||
341 | /************* check for table/array ******************/ | |
342 | case '[': | |
343 | token->type = t1_token_array; | |
344 | ender = ']'; | |
345 | ||
346 | Lookup_Ender: | |
347 | embed = 1; | |
348 | starter = *cur++; | |
349 | token->start = cur; | |
350 | ||
351 | while ( cur < limit ) | |
352 | { | |
353 | if ( *cur == starter ) | |
354 | embed++; | |
355 | else if ( *cur == ender ) | |
356 | { | |
357 | embed--; | |
358 | if ( embed <= 0 ) | |
359 | { | |
360 | token->limit = cur++; | |
361 | break; | |
362 | } | |
363 | } | |
364 | cur++; | |
365 | } | |
366 | break; | |
367 | ||
368 | /* **************** otherwise, it is any token **********/ | |
369 | default: | |
370 | token->start = cur++; | |
371 | token->type = t1_token_any; | |
372 | while ( cur < limit && !IS_CID_SPACE( *cur ) ) | |
373 | cur++; | |
374 | ||
375 | token->limit = cur; | |
376 | } | |
377 | ||
378 | if ( !token->limit ) | |
379 | { | |
380 | token->start = 0; | |
381 | token->type = t1_token_none; | |
382 | } | |
383 | ||
384 | parser->cursor = cur; | |
385 | } | |
386 | } | |
387 | ||
388 | ||
389 | LOCAL_FUNC | |
390 | void CID_ToTokenArray( CID_Parser* parser, | |
391 | CID_Token_Rec* tokens, | |
392 | FT_UInt max_tokens, | |
393 | FT_Int* pnum_tokens ) | |
394 | { | |
395 | CID_Token_Rec master; | |
396 | ||
397 | ||
398 | *pnum_tokens = -1; | |
399 | ||
400 | CID_ToToken( parser, &master ); | |
401 | ||
402 | if ( master.type == t1_token_array ) | |
403 | { | |
404 | FT_Byte* old_cursor = parser->cursor; | |
405 | FT_Byte* old_limit = parser->limit; | |
406 | CID_Token_Rec* cur = tokens; | |
407 | CID_Token_Rec* limit = cur + max_tokens; | |
408 | ||
409 | ||
410 | parser->cursor = master.start; | |
411 | parser->limit = master.limit; | |
412 | ||
413 | while ( parser->cursor < parser->limit ) | |
414 | { | |
415 | CID_Token_Rec token; | |
416 | ||
417 | ||
418 | CID_ToToken( parser, &token ); | |
419 | if ( !token.type ) | |
420 | break; | |
421 | ||
422 | if ( cur < limit ) | |
423 | *cur = token; | |
424 | ||
425 | cur++; | |
426 | } | |
427 | ||
428 | *pnum_tokens = cur - tokens; | |
429 | ||
430 | parser->cursor = old_cursor; | |
431 | parser->limit = old_limit; | |
432 | } | |
433 | } | |
434 | ||
435 | ||
436 | static | |
437 | FT_Long t1_toint( FT_Byte** cursor, | |
438 | FT_Byte* limit ) | |
439 | { | |
440 | FT_Long result = 0; | |
441 | FT_Byte* cur = *cursor; | |
442 | FT_Byte c, d; | |
443 | ||
444 | ||
445 | for ( ; cur < limit; cur++ ) | |
446 | { | |
447 | c = *cur; | |
448 | d = (FT_Byte)( c - '0' ); | |
449 | if ( d < 10 ) | |
450 | break; | |
451 | ||
452 | if ( c == '-' ) | |
453 | { | |
454 | cur++; | |
455 | break; | |
456 | } | |
457 | } | |
458 | ||
459 | if ( cur < limit ) | |
460 | { | |
461 | do | |
462 | { | |
463 | d = (FT_Byte)( cur[0] - '0' ); | |
464 | if ( d >= 10 ) | |
465 | break; | |
466 | ||
467 | result = result * 10 + d; | |
468 | cur++; | |
469 | ||
470 | } while ( cur < limit ); | |
471 | ||
472 | if ( c == '-' ) | |
473 | result = -result; | |
474 | } | |
475 | ||
476 | *cursor = cur; | |
477 | ||
478 | return result; | |
479 | } | |
480 | ||
481 | ||
482 | static | |
483 | FT_Long t1_tofixed( FT_Byte** cursor, | |
484 | FT_Byte* limit, | |
485 | FT_Long power_ten ) | |
486 | { | |
487 | FT_Byte* cur = *cursor; | |
488 | FT_Long num, divider, result; | |
489 | FT_Int sign = 0; | |
490 | FT_Byte d; | |
491 | ||
492 | ||
493 | if ( cur >= limit ) | |
494 | return 0; | |
495 | ||
496 | /* first of all, read the integer part */ | |
497 | result = t1_toint( &cur, limit ) << 16; | |
498 | num = 0; | |
499 | divider = 1; | |
500 | ||
501 | if ( result < 0 ) | |
502 | { | |
503 | sign = 1; | |
504 | result = -result; | |
505 | } | |
506 | ||
507 | if ( cur >= limit ) | |
508 | goto Exit; | |
509 | ||
510 | /* read decimal part, if any */ | |
511 | if ( *cur == '.' && cur + 1 < limit ) | |
512 | { | |
513 | cur++; | |
514 | ||
515 | for (;;) | |
516 | { | |
517 | d = (FT_Byte)( *cur - '0' ); | |
518 | if ( d >= 10 ) | |
519 | break; | |
520 | ||
521 | if ( divider < 10000000L ) | |
522 | { | |
523 | num = num * 10 + d; | |
524 | divider *= 10; | |
525 | } | |
526 | ||
527 | cur++; | |
528 | if ( cur >= limit ) | |
529 | break; | |
530 | } | |
531 | } | |
532 | ||
533 | /* read exponent, if any */ | |
534 | if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) ) | |
535 | { | |
536 | cur++; | |
537 | power_ten += t1_toint( &cur, limit ); | |
538 | } | |
539 | ||
540 | Exit: | |
541 | /* raise to power of ten if needed */ | |
542 | while ( power_ten > 0 ) | |
543 | { | |
544 | result = result * 10; | |
545 | num = num * 10; | |
546 | power_ten--; | |
547 | } | |
548 | ||
549 | while ( power_ten < 0 ) | |
550 | { | |
551 | result = result / 10; | |
552 | divider = divider * 10; | |
553 | power_ten++; | |
554 | } | |
555 | ||
556 | if ( num ) | |
557 | result += FT_DivFix( num, divider ); | |
558 | ||
559 | if ( sign ) | |
560 | result = -result; | |
561 | ||
562 | *cursor = cur; | |
563 | ||
564 | return result; | |
565 | } | |
566 | ||
567 | ||
568 | static | |
569 | int t1_tobool( FT_Byte** cursor, | |
570 | FT_Byte* limit ) | |
571 | { | |
572 | FT_Byte* cur = *cursor; | |
573 | FT_Bool result = 0; | |
574 | ||
575 | ||
576 | /* return 1 if we find a "true", 0 otherwise */ | |
577 | if ( cur + 3 < limit && | |
578 | cur[0] == 't' && | |
579 | cur[1] == 'r' && | |
580 | cur[2] == 'u' && | |
581 | cur[3] == 'e' ) | |
582 | { | |
583 | result = 1; | |
584 | cur += 5; | |
585 | } | |
586 | else if ( cur + 4 < limit && | |
587 | cur[0] == 'f' && | |
588 | cur[1] == 'a' && | |
589 | cur[2] == 'l' && | |
590 | cur[3] == 's' && | |
591 | cur[4] == 'e' ) | |
592 | { | |
593 | result = 0; | |
594 | cur += 6; | |
595 | } | |
596 | *cursor = cur; | |
597 | return result; | |
598 | } | |
599 | ||
600 | ||
601 | static | |
602 | FT_Int t1_tocoordarray( FT_Byte** cursor, | |
603 | FT_Byte* limit, | |
604 | FT_Int max_coords, | |
605 | FT_Short* coords ) | |
606 | { | |
607 | FT_Byte* cur = *cursor; | |
608 | FT_Int count = 0; | |
609 | FT_Byte c, ender; | |
610 | ||
611 | ||
612 | if ( cur >= limit ) | |
613 | goto Exit; | |
614 | ||
615 | /* check for the beginning of an array. */ | |
616 | /* If not, only one number will be read */ | |
617 | c = *cur; | |
618 | ender = 0; | |
619 | ||
620 | if ( c == '[' ) | |
621 | ender = ']'; | |
622 | ||
623 | if ( c == '{' ) | |
624 | ender = '}'; | |
625 | ||
626 | if ( ender ) | |
627 | cur++; | |
628 | ||
629 | /* now, read the coordinates */ | |
630 | for ( ; cur < limit; ) | |
631 | { | |
632 | /* skip whitespace in front of data */ | |
633 | for (;;) | |
634 | { | |
635 | c = *cur; | |
636 | if ( c != ' ' && c != '\t' ) | |
637 | break; | |
638 | ||
639 | cur++; | |
640 | if ( cur >= limit ) | |
641 | goto Exit; | |
642 | } | |
643 | ||
644 | if ( count >= max_coords || c == ender ) | |
645 | break; | |
646 | ||
647 | coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 ); | |
648 | count++; | |
649 | ||
650 | if ( !ender ) | |
651 | break; | |
652 | } | |
653 | ||
654 | Exit: | |
655 | *cursor = cur; | |
656 | return count; | |
657 | } | |
658 | ||
659 | ||
660 | static | |
661 | FT_Int t1_tofixedarray( FT_Byte** cursor, | |
662 | FT_Byte* limit, | |
663 | FT_Int max_values, | |
664 | FT_Fixed* values, | |
665 | FT_Int power_ten ) | |
666 | { | |
667 | FT_Byte* cur = *cursor; | |
668 | FT_Int count = 0; | |
669 | FT_Byte c, ender; | |
670 | ||
671 | ||
672 | if ( cur >= limit ) | |
673 | goto Exit; | |
674 | ||
675 | /* check for the beginning of an array. */ | |
676 | /* If not, only one number will be read */ | |
677 | c = *cur; | |
678 | ender = 0; | |
679 | ||
680 | if ( c == '[' ) | |
681 | ender = ']'; | |
682 | ||
683 | if ( c == '{' ) | |
684 | ender = '}'; | |
685 | ||
686 | if ( ender ) | |
687 | cur++; | |
688 | ||
689 | /* now, read the values */ | |
690 | for ( ; cur < limit; ) | |
691 | { | |
692 | /* skip whitespace in front of data */ | |
693 | for (;;) | |
694 | { | |
695 | c = *cur; | |
696 | if ( c != ' ' && c != '\t' ) | |
697 | break; | |
698 | ||
699 | cur++; | |
700 | if ( cur >= limit ) | |
701 | goto Exit; | |
702 | } | |
703 | ||
704 | if ( count >= max_values || c == ender ) | |
705 | break; | |
706 | ||
707 | values[count] = t1_tofixed( &cur, limit, power_ten ); | |
708 | count++; | |
709 | ||
710 | if ( !ender ) | |
711 | break; | |
712 | } | |
713 | ||
714 | Exit: | |
715 | *cursor = cur; | |
716 | ||
717 | return count; | |
718 | } | |
719 | ||
720 | ||
721 | /* Loads a simple field (i.e. non-table) into the current */ | |
722 | /* list of objects */ | |
723 | LOCAL_FUNC | |
724 | FT_Error CID_Load_Field( CID_Parser* parser, | |
725 | const CID_Field_Rec* field, | |
726 | void* object ) | |
727 | { | |
728 | CID_Token_Rec token; | |
729 | FT_Byte* cur; | |
730 | FT_Byte* limit; | |
731 | FT_UInt count; | |
732 | FT_UInt index; | |
733 | FT_Error error; | |
734 | ||
735 | ||
736 | CID_ToToken( parser, &token ); | |
737 | if ( !token.type ) | |
738 | goto Fail; | |
739 | ||
740 | count = 1; | |
741 | index = 0; | |
742 | cur = token.start; | |
743 | limit = token.limit; | |
744 | ||
745 | { | |
746 | FT_Byte* q = (FT_Byte*)object + field->offset; | |
747 | FT_Long val; | |
748 | FT_String* string; | |
749 | ||
750 | ||
751 | switch ( field->type ) | |
752 | { | |
753 | case t1_field_bool: | |
754 | val = t1_tobool( &cur, limit ); | |
755 | goto Store_Integer; | |
756 | ||
757 | case t1_field_fixed: | |
758 | val = t1_tofixed( &cur, limit, 0 ); | |
759 | goto Store_Integer; | |
760 | ||
761 | case t1_field_integer: | |
762 | val = t1_toint( &cur, limit ); | |
763 | ||
764 | Store_Integer: | |
765 | switch ( field->size ) | |
766 | { | |
767 | case 1: | |
768 | *(FT_Byte*)q = (FT_Byte)val; | |
769 | break; | |
770 | ||
771 | case 2: | |
772 | *(FT_UShort*)q = (FT_UShort)val; | |
773 | break; | |
774 | ||
775 | case 4: | |
776 | *(FT_Int32*)q = (FT_Int)val; | |
777 | break; | |
778 | ||
779 | default: /* for 64-bit systems */ | |
780 | *(FT_Long*)q = val; | |
781 | } | |
782 | break; | |
783 | ||
784 | case t1_field_string: | |
785 | { | |
786 | FT_Memory memory = parser->memory; | |
787 | FT_UInt len = limit-cur; | |
788 | ||
789 | ||
790 | if ( ALLOC( string, len + 1 ) ) | |
791 | goto Exit; | |
792 | ||
793 | MEM_Copy( string, cur, len ); | |
794 | string[len] = 0; | |
795 | ||
796 | *(FT_String**)q = string; | |
797 | } | |
798 | break; | |
799 | ||
800 | default: | |
801 | /* an error occurred */ | |
802 | goto Fail; | |
803 | } | |
804 | } | |
805 | ||
806 | error = 0; | |
807 | ||
808 | Exit: | |
809 | return error; | |
810 | ||
811 | Fail: | |
812 | error = T1_Err_Invalid_File_Format; | |
813 | goto Exit; | |
814 | } | |
815 | ||
816 | ||
817 | #define T1_MAX_TABLE_ELEMENTS 32 | |
818 | ||
819 | ||
820 | LOCAL_FUNC | |
821 | FT_Error CID_Load_Field_Table( CID_Parser* parser, | |
822 | const CID_Field_Rec* field, | |
823 | void* object ) | |
824 | { | |
825 | CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS]; | |
826 | CID_Token_Rec* token; | |
827 | FT_Int num_elements; | |
828 | FT_Error error = 0; | |
829 | FT_Byte* old_cursor; | |
830 | FT_Byte* old_limit; | |
831 | CID_Field_Rec fieldrec = *(CID_Field_Rec*)field; | |
832 | ||
833 | ||
834 | fieldrec.type = t1_field_integer; | |
835 | if ( field->type == t1_field_fixed_array ) | |
836 | fieldrec.type = t1_field_fixed; | |
837 | ||
838 | CID_ToTokenArray( parser, elements, 32, &num_elements ); | |
839 | if ( num_elements < 0 ) | |
840 | goto Fail; | |
841 | ||
842 | if ( num_elements > T1_MAX_TABLE_ELEMENTS ) | |
843 | num_elements = T1_MAX_TABLE_ELEMENTS; | |
844 | ||
845 | old_cursor = parser->cursor; | |
846 | old_limit = parser->limit; | |
847 | ||
848 | /* we store the elements count */ | |
849 | if ( field->count_offset ) | |
850 | *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements; | |
851 | ||
852 | /* we now load each element, adjusting the field.offset on each one */ | |
853 | token = elements; | |
854 | for ( ; num_elements > 0; num_elements--, token++ ) | |
855 | { | |
856 | parser->cursor = token->start; | |
857 | parser->limit = token->limit; | |
858 | CID_Load_Field( parser, &fieldrec, object ); | |
859 | fieldrec.offset += fieldrec.size; | |
860 | } | |
861 | ||
862 | parser->cursor = old_cursor; | |
863 | parser->limit = old_limit; | |
864 | ||
865 | Exit: | |
866 | return error; | |
867 | ||
868 | Fail: | |
869 | error = T1_Err_Invalid_File_Format; | |
870 | goto Exit; | |
871 | } | |
872 | ||
873 | ||
874 | LOCAL_FUNC | |
875 | FT_Long CID_ToInt( CID_Parser* parser ) | |
876 | { | |
877 | return t1_toint( &parser->cursor, parser->limit ); | |
878 | } | |
879 | ||
880 | ||
881 | LOCAL_FUNC | |
882 | FT_Int CID_ToCoordArray( CID_Parser* parser, | |
883 | FT_Int max_coords, | |
884 | FT_Short* coords ) | |
885 | { | |
886 | return t1_tocoordarray( &parser->cursor, parser->limit, | |
887 | max_coords, coords ); | |
888 | } | |
889 | ||
890 | ||
891 | LOCAL_FUNC | |
892 | FT_Int CID_ToFixedArray( CID_Parser* parser, | |
893 | FT_Int max_values, | |
894 | FT_Fixed* values, | |
895 | FT_Int power_ten ) | |
896 | { | |
897 | return t1_tofixedarray( &parser->cursor, parser->limit, | |
898 | max_values, values, power_ten ); | |
899 | } | |
900 | ||
901 | ||
902 | #if 0 | |
903 | ||
904 | /* return the value of an hexadecimal digit */ | |
905 | static | |
906 | int hexa_value( char c ) | |
907 | { | |
908 | unsigned int d; | |
909 | ||
910 | ||
911 | d = (unsigned int)( c - '0' ); | |
912 | if ( d <= 9 ) | |
913 | return (int)d; | |
914 | ||
915 | d = (unsigned int)( c - 'a' ); | |
916 | if ( d <= 5 ) | |
917 | return (int)( d + 10 ); | |
918 | ||
919 | d = (unsigned int)( c - 'A' ); | |
920 | if ( d <= 5 ) | |
921 | return (int)( d + 10 ); | |
922 | ||
923 | return -1; | |
924 | } | |
925 | ||
926 | #endif /* 0 */ | |
927 | ||
928 | ||
929 | LOCAL_FUNC | |
930 | FT_Error CID_New_Parser( CID_Parser* parser, | |
931 | FT_Stream stream, | |
932 | FT_Memory memory ) | |
933 | { | |
934 | FT_Error error; | |
935 | FT_ULong base_offset, offset, ps_len; | |
936 | FT_Byte buffer[256 + 10]; | |
937 | FT_Int buff_len; | |
938 | ||
939 | ||
940 | MEM_Set( parser, 0, sizeof ( *parser ) ); | |
941 | parser->stream = stream; | |
942 | parser->memory = memory; | |
943 | ||
944 | base_offset = FILE_Pos(); | |
945 | ||
946 | /* first of all, check the font format in the header */ | |
947 | if ( ACCESS_Frame( 31 ) ) | |
948 | goto Exit; | |
949 | ||
950 | if ( strncmp( (char *)stream->cursor, | |
951 | "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) | |
952 | { | |
953 | FT_TRACE2(( "[not a valid CID-keyed font]\n" )); | |
954 | error = FT_Err_Unknown_File_Format; | |
955 | } | |
956 | ||
957 | FORGET_Frame(); | |
958 | if ( error ) | |
959 | goto Exit; | |
960 | ||
961 | /* now, read the rest of the file, until we find a `StartData' */ | |
962 | buff_len = 256; | |
963 | for (;;) | |
964 | { | |
965 | FT_Byte *p, *limit = buffer + 256; | |
966 | ||
967 | /* fill input buffer */ | |
968 | buff_len -= 256; | |
969 | if ( buff_len > 0 ) | |
970 | MEM_Move( buffer, limit, buff_len ); | |
971 | ||
972 | if ( FILE_Read( buffer, 256 + 10 - buff_len ) ) | |
973 | goto Exit; | |
974 | ||
975 | buff_len = 256 + 10; | |
976 | ||
977 | /* look for `StartData' */ | |
978 | for ( p = buffer; p < limit; p++ ) | |
979 | { | |
980 | if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 ) | |
981 | { | |
982 | /* save offset of binary data after `StartData' */ | |
983 | offset = FILE_Pos() - ( limit - p ) + 10; | |
984 | goto Found; | |
985 | } | |
986 | } | |
987 | } | |
988 | ||
989 | Found: | |
990 | /* we have found the start of the binary data. We will now */ | |
991 | /* rewind and extract the frame of corresponding to the Postscript */ | |
992 | /* section */ | |
993 | ||
994 | ps_len = offset - base_offset; | |
995 | if ( FILE_Seek( base_offset ) || | |
996 | EXTRACT_Frame( ps_len, parser->postscript ) ) | |
997 | goto Exit; | |
998 | ||
999 | parser->data_offset = offset; | |
1000 | parser->postscript_len = ps_len; | |
1001 | parser->cursor = parser->postscript; | |
1002 | parser->limit = parser->cursor + ps_len; | |
1003 | parser->num_dict = -1; | |
1004 | ||
1005 | Exit: | |
1006 | return error; | |
1007 | } | |
1008 | ||
1009 | ||
1010 | LOCAL_FUNC | |
1011 | void CID_Done_Parser( CID_Parser* parser ) | |
1012 | { | |
1013 | /* always free the private dictionary */ | |
1014 | if ( parser->postscript ) | |
1015 | { | |
1016 | FT_Stream stream = parser->stream; | |
1017 | ||
1018 | ||
1019 | RELEASE_Frame( parser->postscript ); | |
1020 | } | |
1021 | } | |
1022 | ||
1023 | ||
1024 | /* END */ |