]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/type1/t1parse.c
'Y' positioning fixes for OS/2 controls
[wxWidgets.git] / src / freetype / type1 / t1parse.c
1 /***************************************************************************/
2 /* */
3 /* t1parse.c */
4 /* */
5 /* 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 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/t1types.h>
21
22
23 #ifdef FT_FLAT_COMPILE
24
25 #include "t1parse.h"
26
27 #else
28
29 #include <type1/t1parse.h>
30
31 #endif
32
33
34 #include <stdio.h> /* for sscanf() */
35 #include <string.h> /* for strncpy() */
36
37
38 /*************************************************************************/
39 /* */
40 /* <Function> */
41 /* T1_New_Table */
42 /* */
43 /* <Description> */
44 /* Initializes a T1_Table structure. */
45 /* */
46 /* <InOut> */
47 /* table :: The address of the target table. */
48 /* */
49 /* <Input> */
50 /* count :: The table size (i.e. maximum number of elements). */
51 /* memory :: The memory object to use for all subsequent */
52 /* reallocations. */
53 /* */
54 /* <Return> */
55 /* FreeType error code. 0 means success. */
56 /* */
57 LOCAL_FUNC
58 FT_Error T1_New_Table( T1_Table* table,
59 FT_Int count,
60 FT_Memory memory )
61 {
62 FT_Error error;
63
64
65 table->memory = memory;
66
67 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) )
68 return error;
69
70 if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
71 {
72 FREE( table->elements );
73 return error;
74 }
75
76 table->max_elems = count;
77 table->num_elems = 0;
78
79 table->block = 0;
80 table->capacity = 0;
81 table->cursor = 0;
82
83 return error;
84 }
85
86
87 static
88 FT_Error reallocate_t1_table( T1_Table* table,
89 FT_Int new_size )
90 {
91 FT_Memory memory = table->memory;
92 FT_Byte* old_base = table->block;
93 FT_Error error;
94
95
96 /* reallocate the base block */
97 if ( REALLOC( table->block, table->capacity, new_size ) )
98 return error;
99 table->capacity = new_size;
100
101 /* shift all offsets if necessary */
102 if ( old_base )
103 {
104 FT_Long delta = table->block - old_base;
105 FT_Byte** offset = table->elements;
106 FT_Byte** limit = offset + table->max_elems;
107
108
109 if ( delta )
110 for ( ; offset < limit; offset ++ )
111 if (offset[0])
112 offset[0] += delta;
113 }
114
115 return T1_Err_Ok;
116 }
117
118
119 /*************************************************************************/
120 /* */
121 /* <Function> */
122 /* T1_Add_Table */
123 /* */
124 /* <Description> */
125 /* Adds an object to a T1_Table, possibly growing its memory block. */
126 /* */
127 /* <InOut> */
128 /* table :: The target table. */
129 /* */
130 /* <Input> */
131 /* index :: The index of the object in the table. */
132 /* */
133 /* object :: The address of the object to copy in memory. */
134 /* */
135 /* length :: The length in bytes of the source object. */
136 /* */
137 /* <Return> */
138 /* FreeType error code. 0 means success. An error is returned if a */
139 /* reallocation failed. */
140 /* */
141 LOCAL_FUNC
142 FT_Error T1_Add_Table( T1_Table* table,
143 FT_Int index,
144 void* object,
145 FT_Int length )
146 {
147 if ( index < 0 || index > table->max_elems )
148 {
149 FT_ERROR(( "T1_Add_Table: invalid index\n" ));
150 return T1_Err_Syntax_Error;
151 }
152
153 /* grow the base block if needed */
154 if ( table->cursor + length > table->capacity )
155 {
156 FT_Error error;
157 FT_Int new_size = table->capacity;
158
159
160 while ( new_size < table->cursor + length )
161 new_size += 1024;
162
163 error = reallocate_t1_table( table, new_size );
164 if ( error )
165 return error;
166 }
167
168 /* add the object to the base block and adjust offset */
169 table->elements[index] = table->block + table->cursor;
170 table->lengths [index] = length;
171 MEM_Copy( table->block + table->cursor, object, length );
172
173 table->cursor += length;
174
175 return T1_Err_Ok;
176 }
177
178
179 /*************************************************************************/
180 /* */
181 /* <Function> */
182 /* T1_Done_Table */
183 /* */
184 /* <Description> */
185 /* Finalize a T1_Table (reallocate it to its current cursor). */
186 /* */
187 /* <Input> */
188 /* table :: The target table. */
189 /* */
190 /* <Note> */
191 /* This function does NOT release the heap's memory block. It is up */
192 /* to the caller to clean it, or reference it in its own structures. */
193 /* */
194 LOCAL_FUNC
195 void T1_Done_Table( T1_Table* table )
196 {
197 FT_Memory memory = table->memory;
198 FT_Error error;
199 FT_Byte* old_base;
200
201
202 /* should never fail, as rec.cursor <= rec.size */
203 old_base = table->block;
204 if ( !old_base )
205 return;
206
207 (void)REALLOC( table->block, table->capacity, table->cursor );
208 table->capacity = table->cursor;
209
210 if ( old_base != table->block )
211 {
212 FT_Long delta = table->block - old_base;
213 FT_Byte** element = table->elements;
214 FT_Byte** limit = element + table->max_elems;
215
216
217 for ( ; element < limit; element++ )
218 if ( element[0] )
219 element[0] += delta;
220 }
221 }
222
223
224 LOCAL_FUNC
225 FT_String* CopyString( T1_Parser* parser )
226 {
227 FT_String* string = NULL;
228 T1_Token* token = parser->args++;
229 FT_Memory memory = parser->tokenizer->memory;
230 FT_Error error;
231
232
233 if ( token->kind == tok_string )
234 {
235 FT_Int len = token->len - 2;
236
237
238 if ( ALLOC( string, len + 1 ) )
239 {
240 parser->error = error;
241 return 0;
242 }
243
244 MEM_Copy( string, parser->tokenizer->base + token->start + 1, len );
245 string[len] = '\0';
246
247 parser->error = T1_Err_Ok;
248 }
249 else
250 {
251 FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" ));
252 parser->error = T1_Err_Syntax_Error;
253 }
254
255 return string;
256 }
257
258
259 static
260 FT_Error parse_int( FT_Byte* base,
261 FT_Byte* limit,
262 FT_Long* result )
263 {
264 FT_Bool sign = 0;
265 FT_Long sum = 0;
266
267
268 if ( base >= limit )
269 goto Fail;
270
271 /* check sign */
272 if ( *base == '+' )
273 base++;
274
275 else if ( *base == '-' )
276 {
277 sign++;
278 base++;
279 }
280
281 /* parse digits */
282 if ( base >= limit )
283 goto Fail;
284
285 do
286 {
287 sum = ( 10 * sum + ( *base++ - '0' ) );
288
289 } while ( base < limit );
290
291 if ( sign )
292 sum = -sum;
293
294 *result = sum;
295 return T1_Err_Ok;
296
297 Fail:
298 FT_ERROR(( "parse_int: integer expected\n" ));
299 *result = 0;
300 return T1_Err_Syntax_Error;
301 }
302
303
304 static
305 FT_Error parse_float( FT_Byte* base,
306 FT_Byte* limit,
307 FT_Long scale,
308 FT_Long* result )
309 {
310 #if 1
311
312 /* XXX: We are simply much too lazy to code this function */
313 /* properly for now. We will do that when the rest of */
314 /* the driver works properly. */
315 char temp[32];
316 int len = limit - base;
317 double value;
318
319
320 if ( len > 31 )
321 goto Fail;
322
323 strncpy( temp, (char*)base, len );
324 temp[len] = '\0';
325 if ( sscanf( temp, "%lf", &value ) != 1 )
326 goto Fail;
327
328 *result = (FT_Long)( scale * value );
329 return 0;
330
331 #else
332
333 FT_Byte* cur;
334 FT_Bool sign = 0; /* sign */
335 FT_Long number_int = 0; /* integer part */
336 FT_Long number_frac = 0; /* fractional part */
337 FT_Long exponent = 0; /* exponent value */
338 FT_Int num_frac = 0; /* number of fractional digits */
339
340
341 /* check sign */
342 if ( *base == '+' )
343 base++;
344
345 else if ( *base == '-' )
346 {
347 sign++;
348 base++;
349 }
350
351 /* find integer part */
352 cur = base;
353 while ( cur < limit )
354 {
355 FT_Byte c = *cur;
356
357
358 if ( c == '.' || c == 'e' || c == 'E' )
359 break;
360
361 cur++;
362 }
363
364 if ( cur > base )
365 {
366 error = parse_integer( base, cur, &number_int );
367 if ( error )
368 goto Fail;
369 }
370
371 /* read fractional part, if any */
372 if ( *cur == '.' )
373 {
374 cur++;
375 base = cur;
376 while ( cur < limit )
377 {
378 FT_Byte c = *cur;
379
380
381 if ( c == 'e' || c == 'E' )
382 break;
383 cur++;
384 }
385
386 num_frac = cur - base;
387
388 if ( cur > base )
389 {
390 error = parse_integer( base, cur, &number_frac );
391 if ( error )
392 goto Fail;
393 base = cur;
394 }
395 }
396
397 /* read exponent, if any */
398 if ( *cur == 'e' || *cur == 'E' )
399 {
400 cur++;
401 base = cur;
402 error = parse_integer( base, limit, &exponent );
403 if ( error )
404 goto Fail;
405
406 /* now check that exponent is within `correct bounds' */
407 /* i.e. between -6 and 6 */
408 if ( exponent < -6 || exponent > 6 )
409 goto Fail;
410 }
411
412 /* now adjust integer value and exponent for fractional part */
413 while ( num_frac > 0 )
414 {
415 number_int *= 10;
416 exponent--;
417 num_frac--;
418 }
419
420 number_int += num_frac;
421
422 /* skip point if any, read fractional part */
423 if ( cur + 1 < limit )
424 {
425 if (*cur..
426 }
427
428 /* now compute scaled float value */
429 /* XXX: incomplete! */
430
431 #endif /* 1 */
432
433 Fail:
434 FT_ERROR(( "parse_float: syntax error!\n" ));
435 return T1_Err_Syntax_Error;
436 }
437
438
439 static
440 FT_Error parse_integer( FT_Byte* base,
441 FT_Byte* limit,
442 FT_Long* result )
443 {
444 FT_Byte* cur;
445
446
447 /* the lexical analyser accepts floats as well as integers */
448 /* now; check that we really have an int in this token */
449 cur = base;
450 while ( cur < limit )
451 {
452 FT_Byte c = *cur++;
453
454
455 if ( c == '.' || c == 'e' || c == 'E' )
456 goto Float_Number;
457 }
458
459 /* now read the number's value */
460 return parse_int( base, limit, result );
461
462 Float_Number:
463 /* we really have a float there; simply call parse_float in this */
464 /* case with a scale of `10' to perform round */
465 {
466 FT_Error error;
467
468
469 error = parse_float( base, limit, 10, result );
470 if ( !error )
471 {
472 if ( *result >= 0 )
473 *result = ( *result + 5 ) / 10; /* round value */
474 else
475 *result = -( ( 5 - *result ) / 10 );
476 }
477 return error;
478 }
479 }
480
481
482 LOCAL_FUNC
483 FT_Long CopyInteger( T1_Parser* parser )
484 {
485 FT_Long sum = 0;
486 T1_Token* token = parser->args++;
487
488
489 if ( token->kind == tok_number )
490 {
491 FT_Byte* base = parser->tokenizer->base + token->start;
492 FT_Byte* limit = base + token->len;
493
494
495 /* now read the number's value */
496 parser->error = parse_integer( base, limit, &sum );
497 return sum;
498 }
499
500 FT_ERROR(( "CopyInteger: number expected\n" ));
501 parser->args--;
502 parser->error = T1_Err_Syntax_Error;
503 return 0;
504 }
505
506
507 LOCAL_FUNC
508 FT_Bool CopyBoolean( T1_Parser* parser )
509 {
510 FT_Error error = T1_Err_Ok;
511 FT_Bool result = 0;
512 T1_Token* token = parser->args++;
513
514
515 if ( token->kind == tok_keyword )
516 {
517 if ( token->kind2 == key_false )
518 result = 0;
519
520 else if ( token->kind2 == key_true )
521 result = !0;
522
523 else
524 goto Fail;
525 }
526 else
527 {
528 Fail:
529 FT_ERROR(( "CopyBoolean:" ));
530 FT_ERROR(( " syntax error; `false' or `true' expected\n" ));
531 error = T1_Err_Syntax_Error;
532 }
533 parser->error = error;
534 return result;
535 }
536
537
538 LOCAL_FUNC
539 FT_Long CopyFloat( T1_Parser* parser,
540 FT_Int scale )
541 {
542 FT_Error error;
543 FT_Long sum = 0;
544 T1_Token* token = parser->args++;
545
546
547 if ( token->kind == tok_number )
548 {
549 FT_Byte* base = parser->tokenizer->base + token->start;
550 FT_Byte* limit = base + token->len;
551
552
553 error = parser->error = parse_float( base, limit, scale, &sum );
554 if ( error )
555 goto Fail;
556
557 return sum;
558 }
559
560 Fail:
561 FT_ERROR(( "CopyFloat: syntax error!\n" ));
562 parser->error = T1_Err_Syntax_Error;
563 return 0;
564 }
565
566
567 LOCAL_FUNC
568 void CopyBBox( T1_Parser* parser,
569 FT_BBox* bbox )
570 {
571 T1_Token* token = parser->args++;
572 FT_Int n;
573 FT_Error error;
574
575
576 if ( token->kind == tok_program ||
577 token->kind == tok_array )
578 {
579 /* get rid of `['/`]', or `{'/`}' */
580 FT_Byte* base = parser->tokenizer->base + token->start + 1;
581 FT_Byte* limit = base + token->len - 2;
582 FT_Byte* cur;
583 FT_Byte* start;
584
585
586 /* read each parameter independently */
587 cur = base;
588 for ( n = 0; n < 4; n++ )
589 {
590 FT_Long* result;
591
592
593 /* skip whitespace */
594 while ( cur < limit && *cur == ' ' )
595 cur++;
596
597 /* skip numbers */
598 start = cur;
599 while ( cur < limit && *cur != ' ' )
600 cur++;
601
602 /* compute result address */
603 switch ( n )
604 {
605 case 0:
606 result = &bbox->xMin;
607 break;
608 case 1:
609 result = &bbox->yMin;
610 break;
611 case 2:
612 result = &bbox->xMax;
613 break;
614 default:
615 result = &bbox->yMax;
616 }
617
618 error = parse_integer( start, cur, result );
619 if ( error )
620 goto Fail;
621 }
622 parser->error = 0;
623 return;
624 }
625
626 Fail:
627 FT_ERROR(( "CopyBBox: syntax error!\n" ));
628 parser->error = T1_Err_Syntax_Error;
629 }
630
631
632 LOCAL_FUNC
633 void CopyMatrix( T1_Parser* parser,
634 FT_Matrix* matrix )
635 {
636 T1_Token* token = parser->args++;
637 FT_Error error;
638
639
640 if ( token->kind == tok_array )
641 {
642 /* get rid of `[' and `]' */
643 FT_Byte* base = parser->tokenizer->base + token->start + 1;
644 FT_Byte* limit = base + token->len - 2;
645 FT_Byte* cur;
646 FT_Byte* start;
647 FT_Int n;
648
649
650 /* read each parameter independently */
651 cur = base;
652 for ( n = 0; n < 4; n++ )
653 {
654 FT_Long* result;
655
656
657 /* skip whitespace */
658 while ( cur < limit && *cur == ' ' )
659 cur++;
660
661 /* skip numbers */
662 start = cur;
663 while ( cur < limit && *cur != ' ')
664 cur++;
665
666 /* compute result address */
667 switch ( n )
668 {
669 case 0:
670 result = &matrix->xx;
671 break;
672 case 1:
673 result = &matrix->yx;
674 break;
675 case 2:
676 result = &matrix->xy;
677 break;
678 default:
679 result = &matrix->yy;
680 }
681
682 error = parse_float( start, cur, 65536000L, result );
683 if ( error )
684 goto Fail;
685 }
686 parser->error = 0;
687 return;
688 }
689
690 Fail:
691 FT_ERROR(( "CopyMatrix: syntax error!\n" ));
692 parser->error = T1_Err_Syntax_Error;
693 }
694
695
696 LOCAL_FUNC
697 void CopyArray( T1_Parser* parser,
698 FT_Byte* num_elements,
699 FT_Short* elements,
700 FT_Int max_elements )
701 {
702 T1_Token* token = parser->args++;
703 FT_Error error;
704
705
706 if ( token->kind == tok_array ||
707 token->kind == tok_program ) /* in the case of MinFeature */
708 {
709 /* get rid of `['/`]', or `{'/`}' */
710 FT_Byte* base = parser->tokenizer->base + token->start + 1;
711 FT_Byte* limit = base + token->len - 2;
712 FT_Byte* cur;
713 FT_Byte* start;
714 FT_Int n;
715
716
717 /* read each parameter independently */
718 cur = base;
719 for ( n = 0; n < max_elements; n++ )
720 {
721 FT_Long result;
722
723
724 /* test end of string */
725 if ( cur >= limit )
726 break;
727
728 /* skip whitespace */
729 while ( cur < limit && *cur == ' ' )
730 cur++;
731
732 /* end of list? */
733 if ( cur >= limit )
734 break;
735
736 /* skip numbers */
737 start = cur;
738 while ( cur < limit && *cur != ' ' )
739 cur++;
740
741 error = parse_integer( start, cur, &result );
742 if ( error )
743 goto Fail;
744
745 *elements++ = (FT_Short)result;
746 }
747
748 if ( num_elements )
749 *num_elements = (FT_Byte)n;
750
751 parser->error = 0;
752 return;
753 }
754
755 Fail:
756 FT_ERROR(( "CopyArray: syntax error!\n" ));
757 parser->error = T1_Err_Syntax_Error;
758 }
759
760
761 /* END */