1 /***************************************************************************/
5 /* Type 1 parser (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/t1types.h>
23 #ifdef FT_FLAT_COMPILE
29 #include <freetype/src/type1/t1parse.h>
34 #include <stdio.h> /* for sscanf() */
35 #include <string.h> /* for strncpy() */
38 /*************************************************************************/
44 /* Initializes a T1_Table structure. */
47 /* table :: The address of the target table. */
50 /* count :: The table size (i.e. maximum number of elements). */
51 /* memory :: The memory object to use for all subsequent */
55 /* FreeType error code. 0 means success. */
58 FT_Error T1_New_Table( T1_Table* table,
65 table->memory = memory;
67 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) )
70 if ( ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
72 FREE( table->elements );
76 table->max_elems = count;
88 FT_Error reallocate_t1_table( T1_Table* table,
91 FT_Memory memory = table->memory;
92 FT_Byte* old_base = table->block;
96 /* reallocate the base block */
97 if ( REALLOC( table->block, table->capacity, new_size ) )
99 table->capacity = new_size;
101 /* shift all offsets if necessary */
104 FT_Long delta = table->block - old_base;
105 FT_Byte** offset = table->elements;
106 FT_Byte** limit = offset + table->max_elems;
110 for ( ; offset < limit; offset ++ )
119 /*************************************************************************/
125 /* Adds an object to a T1_Table, possibly growing its memory block. */
128 /* table :: The target table. */
131 /* index :: The index of the object in the table. */
133 /* object :: The address of the object to copy in memory. */
135 /* length :: The length in bytes of the source object. */
138 /* FreeType error code. 0 means success. An error is returned if a */
139 /* reallocation failed. */
142 FT_Error T1_Add_Table( T1_Table* table,
147 if ( index < 0 || index > table->max_elems )
149 FT_ERROR(( "T1_Add_Table: invalid index\n" ));
150 return T1_Err_Syntax_Error;
153 /* grow the base block if needed */
154 if ( table->cursor + length > table->capacity )
157 FT_Int new_size = table->capacity;
160 while ( new_size < table->cursor + length )
163 error = reallocate_t1_table( table, new_size );
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 );
173 table->cursor += length;
179 /*************************************************************************/
185 /* Finalize a T1_Table (reallocate it to its current cursor). */
188 /* table :: The target table. */
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. */
195 void T1_Done_Table( T1_Table* table )
197 FT_Memory memory = table->memory;
202 /* should never fail, as rec.cursor <= rec.size */
203 old_base = table->block;
207 (void)REALLOC( table->block, table->capacity, table->cursor );
208 table->capacity = table->cursor;
210 if ( old_base != table->block )
212 FT_Long delta = table->block - old_base;
213 FT_Byte** element = table->elements;
214 FT_Byte** limit = element + table->max_elems;
217 for ( ; element < limit; element++ )
225 FT_String* CopyString( T1_Parser* parser )
227 FT_String* string = NULL;
228 T1_Token* token = parser->args++;
229 FT_Memory memory = parser->tokenizer->memory;
233 if ( token->kind == tok_string )
235 FT_Int len = token->len - 2;
238 if ( ALLOC( string, len + 1 ) )
240 parser->error = error;
244 MEM_Copy( string, parser->tokenizer->base + token->start + 1, len );
247 parser->error = T1_Err_Ok;
251 FT_ERROR(( "T1_CopyString: syntax error, string token expected!\n" ));
252 parser->error = T1_Err_Syntax_Error;
260 FT_Error parse_int( FT_Byte* base,
275 else if ( *base == '-' )
287 sum = ( 10 * sum + ( *base++ - '0' ) );
289 } while ( base < limit );
298 FT_ERROR(( "parse_int: integer expected\n" ));
300 return T1_Err_Syntax_Error;
305 FT_Error parse_float( FT_Byte* base,
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. */
316 int len = limit - base;
323 strncpy( temp, (char*)base, len );
325 if ( sscanf( temp, "%lf", &value ) != 1 )
328 *result = (FT_Long)( scale * value );
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 */
345 else if ( *base == '-' )
351 /* find integer part */
353 while ( cur < limit )
358 if ( c == '.' || c == 'e' || c == 'E' )
366 error = parse_integer( base, cur, &number_int );
371 /* read fractional part, if any */
376 while ( cur < limit )
381 if ( c == 'e' || c == 'E' )
386 num_frac = cur - base;
390 error = parse_integer( base, cur, &number_frac );
397 /* read exponent, if any */
398 if ( *cur == 'e' || *cur == 'E' )
402 error = parse_integer( base, limit, &exponent );
406 /* now check that exponent is within `correct bounds' */
407 /* i.e. between -6 and 6 */
408 if ( exponent < -6 || exponent > 6 )
412 /* now adjust integer value and exponent for fractional part */
413 while ( num_frac > 0 )
420 number_int += num_frac;
422 /* skip point if any, read fractional part */
423 if ( cur + 1 < limit )
428 /* now compute scaled float value */
429 /* XXX: incomplete! */
434 FT_ERROR(( "parse_float: syntax error!\n" ));
435 return T1_Err_Syntax_Error;
440 FT_Error parse_integer( FT_Byte* base,
447 /* the lexical analyser accepts floats as well as integers */
448 /* now; check that we really have an int in this token */
450 while ( cur < limit )
455 if ( c == '.' || c == 'e' || c == 'E' )
459 /* now read the number's value */
460 return parse_int( base, limit, result );
463 /* we really have a float there; simply call parse_float in this */
464 /* case with a scale of `10' to perform round */
469 error = parse_float( base, limit, 10, result );
473 *result = ( *result + 5 ) / 10; /* round value */
475 *result = -( ( 5 - *result ) / 10 );
483 FT_Long CopyInteger( T1_Parser* parser )
486 T1_Token* token = parser->args++;
489 if ( token->kind == tok_number )
491 FT_Byte* base = parser->tokenizer->base + token->start;
492 FT_Byte* limit = base + token->len;
495 /* now read the number's value */
496 parser->error = parse_integer( base, limit, &sum );
500 FT_ERROR(( "CopyInteger: number expected\n" ));
502 parser->error = T1_Err_Syntax_Error;
508 FT_Bool CopyBoolean( T1_Parser* parser )
510 FT_Error error = T1_Err_Ok;
512 T1_Token* token = parser->args++;
515 if ( token->kind == tok_keyword )
517 if ( token->kind2 == key_false )
520 else if ( token->kind2 == key_true )
529 FT_ERROR(( "CopyBoolean:" ));
530 FT_ERROR(( " syntax error; `false' or `true' expected\n" ));
531 error = T1_Err_Syntax_Error;
533 parser->error = error;
539 FT_Long CopyFloat( T1_Parser* parser,
544 T1_Token* token = parser->args++;
547 if ( token->kind == tok_number )
549 FT_Byte* base = parser->tokenizer->base + token->start;
550 FT_Byte* limit = base + token->len;
553 error = parser->error = parse_float( base, limit, scale, &sum );
561 FT_ERROR(( "CopyFloat: syntax error!\n" ));
562 parser->error = T1_Err_Syntax_Error;
568 void CopyBBox( T1_Parser* parser,
571 T1_Token* token = parser->args++;
576 if ( token->kind == tok_program ||
577 token->kind == tok_array )
579 /* get rid of `['/`]', or `{'/`}' */
580 FT_Byte* base = parser->tokenizer->base + token->start + 1;
581 FT_Byte* limit = base + token->len - 2;
586 /* read each parameter independently */
588 for ( n = 0; n < 4; n++ )
593 /* skip whitespace */
594 while ( cur < limit && *cur == ' ' )
599 while ( cur < limit && *cur != ' ' )
602 /* compute result address */
606 result = &bbox->xMin;
609 result = &bbox->yMin;
612 result = &bbox->xMax;
615 result = &bbox->yMax;
618 error = parse_integer( start, cur, result );
627 FT_ERROR(( "CopyBBox: syntax error!\n" ));
628 parser->error = T1_Err_Syntax_Error;
633 void CopyMatrix( T1_Parser* parser,
636 T1_Token* token = parser->args++;
640 if ( token->kind == tok_array )
642 /* get rid of `[' and `]' */
643 FT_Byte* base = parser->tokenizer->base + token->start + 1;
644 FT_Byte* limit = base + token->len - 2;
650 /* read each parameter independently */
652 for ( n = 0; n < 4; n++ )
657 /* skip whitespace */
658 while ( cur < limit && *cur == ' ' )
663 while ( cur < limit && *cur != ' ')
666 /* compute result address */
670 result = &matrix->xx;
673 result = &matrix->yx;
676 result = &matrix->xy;
679 result = &matrix->yy;
682 error = parse_float( start, cur, 65536000L, result );
691 FT_ERROR(( "CopyMatrix: syntax error!\n" ));
692 parser->error = T1_Err_Syntax_Error;
697 void CopyArray( T1_Parser* parser,
698 FT_Byte* num_elements,
700 FT_Int max_elements )
702 T1_Token* token = parser->args++;
706 if ( token->kind == tok_array ||
707 token->kind == tok_program ) /* in the case of MinFeature */
709 /* get rid of `['/`]', or `{'/`}' */
710 FT_Byte* base = parser->tokenizer->base + token->start + 1;
711 FT_Byte* limit = base + token->len - 2;
717 /* read each parameter independently */
719 for ( n = 0; n < max_elements; n++ )
724 /* test end of string */
728 /* skip whitespace */
729 while ( cur < limit && *cur == ' ' )
738 while ( cur < limit && *cur != ' ' )
741 error = parse_integer( start, cur, &result );
745 *elements++ = (FT_Short)result;
749 *num_elements = (FT_Byte)n;
756 FT_ERROR(( "CopyArray: syntax error!\n" ));
757 parser->error = T1_Err_Syntax_Error;