1 /***************************************************************************/
5 /* Auxiliary functions for PostScript fonts (body). */
7 /* Copyright 1996-2001, 2002 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 /***************************************************************************/
20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
21 #include FT_INTERNAL_DEBUG_H
28 /*************************************************************************/
29 /*************************************************************************/
31 /***** PS_TABLE *****/
33 /*************************************************************************/
34 /*************************************************************************/
36 /*************************************************************************/
42 /* Initializes a PS_Table. */
45 /* table :: The address of the target table. */
48 /* count :: The table size = the maximum number of elements. */
50 /* memory :: The memory object to use for all subsequent */
54 /* FreeType error code. 0 means success. */
56 FT_LOCAL_DEF( FT_Error )
57 ps_table_new( PS_Table table,
64 table->memory = memory;
65 if ( FT_NEW_ARRAY( table->elements, count ) ||
66 FT_NEW_ARRAY( table->lengths, count ) )
69 table->max_elems = count;
70 table->init = 0xDEADBEEFUL;
76 *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
80 FT_FREE( table->elements );
87 shift_elements( PS_Table table,
90 FT_Long delta = (FT_Long)( table->block - old_base );
91 FT_Byte** offset = table->elements;
92 FT_Byte** limit = offset + table->max_elems;
95 for ( ; offset < limit; offset++ )
104 reallocate_t1_table( PS_Table table,
107 FT_Memory memory = table->memory;
108 FT_Byte* old_base = table->block;
112 /* allocate new base block */
113 if ( FT_ALLOC( table->block, new_size ) )
115 table->block = old_base;
119 /* copy elements and shift offsets */
122 FT_MEM_COPY( table->block, old_base, table->capacity );
123 shift_elements( table, old_base );
127 table->capacity = new_size;
133 /*************************************************************************/
139 /* Adds an object to a PS_Table, possibly growing its memory block. */
142 /* table :: The target table. */
145 /* idx :: The index of the object in the table. */
147 /* object :: The address of the object to copy in memory. */
149 /* length :: The length in bytes of the source object. */
152 /* FreeType error code. 0 means success. An error is returned if a */
153 /* reallocation fails. */
155 FT_LOCAL_DEF( FT_Error )
156 ps_table_add( PS_Table table,
161 if ( idx < 0 || idx > table->max_elems )
163 FT_ERROR(( "ps_table_add: invalid index\n" ));
164 return PSaux_Err_Invalid_Argument;
167 /* grow the base block if needed */
168 if ( table->cursor + length > table->capacity )
171 FT_Offset new_size = table->capacity;
175 in_offset = (FT_Long)((FT_Byte*)object - table->block);
176 if ( (FT_ULong)in_offset >= table->capacity )
179 while ( new_size < table->cursor + length )
181 /* increase size by 25% and round up to the nearest multiple of 1024 */
182 new_size += (new_size >> 2) + 1;
183 new_size = ( new_size + 1023 ) & -1024;
186 error = reallocate_t1_table( table, new_size );
190 if ( in_offset >= 0 )
191 object = table->block + in_offset;
194 /* add the object to the base block and adjust offset */
195 table->elements[idx] = table->block + table->cursor;
196 table->lengths [idx] = length;
197 FT_MEM_COPY( table->block + table->cursor, object, length );
199 table->cursor += length;
204 /*************************************************************************/
210 /* Finalizes a PS_TableRec (i.e., reallocate it to its current */
214 /* table :: The target table. */
217 /* This function does NOT release the heap's memory block. It is up */
218 /* to the caller to clean it, or reference it in its own structures. */
221 ps_table_done( PS_Table table )
223 FT_Memory memory = table->memory;
225 FT_Byte* old_base = table->block;
228 /* should never fail, because rec.cursor <= rec.size */
232 if ( FT_ALLOC( table->block, table->cursor ) )
234 FT_MEM_COPY( table->block, old_base, table->cursor );
235 shift_elements( table, old_base );
237 table->capacity = table->cursor;
245 ps_table_release( PS_Table table )
247 FT_Memory memory = table->memory;
250 if ( (FT_ULong)table->init == 0xDEADBEEFUL )
252 FT_FREE( table->block );
253 FT_FREE( table->elements );
254 FT_FREE( table->lengths );
260 /*************************************************************************/
261 /*************************************************************************/
263 /***** T1 PARSER *****/
265 /*************************************************************************/
266 /*************************************************************************/
269 #define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
270 #define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
272 #define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
276 ps_parser_skip_spaces( PS_Parser parser )
278 FT_Byte* cur = parser->cursor;
279 FT_Byte* limit = parser->limit;
282 while ( cur < limit )
287 if ( !IS_T1_SPACE( c ) )
291 parser->cursor = cur;
296 ps_parser_skip_alpha( PS_Parser parser )
298 FT_Byte* cur = parser->cursor;
299 FT_Byte* limit = parser->limit;
302 while ( cur < limit )
307 if ( IS_T1_SPACE( c ) )
311 parser->cursor = cur;
316 ps_parser_to_token( PS_Parser parser,
321 FT_Byte starter, ender;
325 token->type = T1_TOKEN_TYPE_NONE;
329 /* first of all, skip space */
330 ps_parser_skip_spaces( parser );
332 cur = parser->cursor;
333 limit = parser->limit;
339 /************* check for strings ***********************/
341 token->type = T1_TOKEN_TYPE_STRING;
345 /************* check for programs/array ****************/
347 token->type = T1_TOKEN_TYPE_ARRAY;
351 /************* check for table/array ******************/
353 token->type = T1_TOKEN_TYPE_ARRAY;
360 while ( cur < limit )
362 if ( *cur == starter )
364 else if ( *cur == ender )
369 token->limit = cur++;
377 /* **************** otherwise, it's any token **********/
379 token->start = cur++;
380 token->type = T1_TOKEN_TYPE_ANY;
381 while ( cur < limit && !IS_T1_SPACE( *cur ) )
390 token->type = T1_TOKEN_TYPE_NONE;
393 parser->cursor = cur;
399 ps_parser_to_token_array( PS_Parser parser,
402 FT_Int* pnum_tokens )
409 ps_parser_to_token( parser, &master );
410 if ( master.type == T1_TOKEN_TYPE_ARRAY )
412 FT_Byte* old_cursor = parser->cursor;
413 FT_Byte* old_limit = parser->limit;
414 T1_Token cur = tokens;
415 T1_Token limit = cur + max_tokens;
418 parser->cursor = master.start;
419 parser->limit = master.limit;
421 while ( parser->cursor < parser->limit )
426 ps_parser_to_token( parser, &token );
436 *pnum_tokens = (FT_Int)( cur - tokens );
438 parser->cursor = old_cursor;
439 parser->limit = old_limit;
445 T1Radix( FT_Long radixBase,
450 FT_Byte radixEndChar0 =
451 (FT_Byte)( radixBase > 10 ? '9' + 1 : '0' + radixBase );
452 FT_Byte radixEndChar1 =
453 (FT_Byte)( 'A' + radixBase - 10 );
454 FT_Byte radixEndChar2 =
455 (FT_Byte)( 'a' + radixBase - 10 );
458 while( *cur < limit )
460 if ( (*cur)[0] >= '0' && (*cur)[0] < radixEndChar0 )
461 result = result * radixBase + (*cur)[0] - '0';
463 else if ( radixBase > 10 &&
464 (*cur)[0] >= 'A' && (*cur)[0] < radixEndChar1 )
465 result = result * radixBase + ( (*cur)[0] - 'A' + 10 );
467 else if ( radixBase > 10 &&
468 (*cur)[0] >= 'a' && (*cur)[0] < radixEndChar2 )
469 result = result * radixBase + ( (*cur)[0] - 'a' + 10 );
482 t1_toint( FT_Byte** cursor,
486 FT_Byte* cur = *cursor;
490 for ( ; cur < limit; cur++ )
493 d = (FT_Byte)( c - '0' );
508 d = (FT_Byte)( cur[0] - '0' );
514 result = T1Radix( result, &cur, limit );
519 result = result * 10 + d;
522 } while ( cur < limit );
534 t1_tofixed( FT_Byte** cursor,
538 FT_Byte* cur = *cursor;
539 FT_Long num, divider, result;
547 /* first of all, check the sign */
554 /* then, read the integer part, if any */
556 result = t1_toint( &cur, limit ) << 16;
566 /* read decimal part, if any */
567 if ( *cur == '.' && cur + 1 < limit )
573 d = (FT_Byte)( *cur - '0' );
577 if ( divider < 10000000L )
589 /* read exponent, if any */
590 if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
593 power_ten += t1_toint( &cur, limit );
597 /* raise to power of ten if needed */
598 while ( power_ten > 0 )
600 result = result * 10;
605 while ( power_ten < 0 )
607 result = result / 10;
608 divider = divider * 10;
613 result += FT_DivFix( num, divider );
624 t1_tocoordarray( FT_Byte** cursor,
629 FT_Byte* cur = *cursor;
637 /* check for the beginning of an array; if not, only one number will */
651 /* now, read the coordinates */
652 for ( ; cur < limit; )
654 /* skip whitespace in front of data */
658 if ( c != ' ' && c != '\t' )
666 if ( count >= max_coords || c == ender )
669 coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
683 t1_tofixedarray( FT_Byte** cursor,
689 FT_Byte* cur = *cursor;
694 if ( cur >= limit ) goto Exit;
696 /* check for the beginning of an array. If not, only one number will */
710 /* now, read the values */
711 for ( ; cur < limit; )
713 /* skip whitespace in front of data */
717 if ( c != ' ' && c != '\t' )
725 if ( count >= max_values || c == ender )
728 values[count] = t1_tofixed( &cur, limit, power_ten );
744 t1_tostring( FT_Byte** cursor,
748 FT_Byte* cur = *cursor;
755 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
756 /* that simply doesn't begin with an opening parenthesis, even */
757 /* though they have a closing one! E.g. "amuncial.pfb" */
759 /* We must deal with these ill-fated cases there. Note that */
760 /* these fonts didn't work with the old Type 1 driver as the */
761 /* notice/copyright was not recognized as a valid string token */
762 /* and made the old token parser commit errors. */
764 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
766 if ( cur + 1 >= limit )
770 cur++; /* skip the opening parenthesis, if there is one */
775 /* then, count its length */
776 for ( ; cur < limit; cur++ )
781 else if ( *cur == ')' )
790 if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
793 /* now copy the string */
794 FT_MEM_COPY( result, *cursor, len );
804 t1_tobool( FT_Byte** cursor,
807 FT_Byte* cur = *cursor;
811 /* return 1 if we find `true', 0 otherwise */
812 if ( cur + 3 < limit &&
821 else if ( cur + 4 < limit &&
837 /* Load a simple field (i.e. non-table) into the current list of objects */
838 FT_LOCAL_DEF( FT_Error )
839 ps_parser_load_field( PS_Parser parser,
840 const T1_Field field,
853 ps_parser_to_token( parser, &token );
862 /* we must detect arrays */
863 if ( field->type == T1_FIELD_TYPE_BBOX )
866 FT_Byte* old_cur = parser->cursor;
867 FT_Byte* old_limit = parser->limit;
870 parser->cursor = token.start;
871 parser->limit = token.limit;
873 ps_parser_to_token( parser, &token2 );
874 parser->cursor = old_cur;
875 parser->limit = old_limit;
877 if ( token2.type == T1_TOKEN_TYPE_ARRAY )
880 else if ( token.type == T1_TOKEN_TYPE_ARRAY )
883 /* if this is an array, and we have no blend, an error occurs */
884 if ( max_objects == 0 )
891 for ( ; count > 0; count--, idx++ )
893 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
898 switch ( field->type )
900 case T1_FIELD_TYPE_BOOL:
901 val = t1_tobool( &cur, limit );
904 case T1_FIELD_TYPE_FIXED:
905 val = t1_tofixed( &cur, limit, 3 );
908 case T1_FIELD_TYPE_INTEGER:
909 val = t1_toint( &cur, limit );
912 switch ( field->size )
915 *(FT_Byte*)q = (FT_Byte)val;
919 *(FT_UShort*)q = (FT_UShort)val;
923 *(FT_UInt32*)q = (FT_UInt32)val;
926 default: /* for 64-bit systems */
931 case T1_FIELD_TYPE_STRING:
933 FT_Memory memory = parser->memory;
934 FT_UInt len = (FT_UInt)( limit - cur );
937 if ( *(FT_String**)q )
938 /* with synthetic fonts, it's possible to find a field twice */
941 if ( FT_ALLOC( string, len + 1 ) )
944 FT_MEM_COPY( string, cur, len );
947 *(FT_String**)q = string;
951 case T1_FIELD_TYPE_BBOX:
954 FT_BBox* bbox = (FT_BBox*)q;
957 /* we need the '[' and ']' delimiters */
960 (void)t1_tofixedarray( &token.start, token.limit, 4, temp, 0 );
962 bbox->xMin = FT_RoundFix( temp[0] );
963 bbox->yMin = FT_RoundFix( temp[1] );
964 bbox->xMax = FT_RoundFix( temp[2] );
965 bbox->yMax = FT_RoundFix( temp[3] );
970 /* an error occured */
975 #if 0 /* obsolete - keep for reference */
977 *pflags |= 1L << field->flag_bit;
982 error = PSaux_Err_Ok;
988 error = PSaux_Err_Invalid_File_Format;
993 #define T1_MAX_TABLE_ELEMENTS 32
996 FT_LOCAL_DEF( FT_Error )
997 ps_parser_load_field_table( PS_Parser parser,
998 const T1_Field field,
1000 FT_UInt max_objects,
1003 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
1005 FT_Int num_elements;
1007 FT_Byte* old_cursor;
1009 T1_FieldRec fieldrec = *(T1_Field)field;
1013 fieldrec.type = T1_FIELD_TYPE_INTEGER;
1014 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1015 fieldrec.type = T1_FIELD_TYPE_FIXED;
1018 ps_parser_to_token_array( parser, elements, 32, &num_elements );
1019 if ( num_elements < 0 )
1022 if ( num_elements > T1_MAX_TABLE_ELEMENTS )
1023 num_elements = T1_MAX_TABLE_ELEMENTS;
1025 old_cursor = parser->cursor;
1026 old_limit = parser->limit;
1028 /* we store the elements count */
1029 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1030 (FT_Byte)num_elements;
1032 /* we now load each element, adjusting the field.offset on each one */
1034 for ( ; num_elements > 0; num_elements--, token++ )
1036 parser->cursor = token->start;
1037 parser->limit = token->limit;
1038 ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
1039 fieldrec.offset += fieldrec.size;
1042 #if 0 /* obsolete -- keep for reference */
1044 *pflags |= 1L << field->flag_bit;
1046 FT_UNUSED( pflags );
1049 parser->cursor = old_cursor;
1050 parser->limit = old_limit;
1056 error = PSaux_Err_Invalid_File_Format;
1061 FT_LOCAL_DEF( FT_Long )
1062 ps_parser_to_int( PS_Parser parser )
1064 return t1_toint( &parser->cursor, parser->limit );
1068 FT_LOCAL_DEF( FT_Fixed )
1069 ps_parser_to_fixed( PS_Parser parser,
1072 return t1_tofixed( &parser->cursor, parser->limit, power_ten );
1076 FT_LOCAL_DEF( FT_Int )
1077 ps_parser_to_coord_array( PS_Parser parser,
1081 return t1_tocoordarray( &parser->cursor, parser->limit,
1082 max_coords, coords );
1086 FT_LOCAL_DEF( FT_Int )
1087 ps_parser_to_fixed_array( PS_Parser parser,
1092 return t1_tofixedarray( &parser->cursor, parser->limit,
1093 max_values, values, power_ten );
1099 FT_LOCAL_DEF( FT_String* )
1100 T1_ToString( PS_Parser parser )
1102 return t1_tostring( &parser->cursor, parser->limit, parser->memory );
1106 FT_LOCAL_DEF( FT_Bool )
1107 T1_ToBool( PS_Parser parser )
1109 return t1_tobool( &parser->cursor, parser->limit );
1115 FT_LOCAL_DEF( void )
1116 ps_parser_init( PS_Parser parser,
1122 parser->base = base;
1123 parser->limit = limit;
1124 parser->cursor = base;
1125 parser->memory = memory;
1126 parser->funcs = ps_parser_funcs;
1130 FT_LOCAL_DEF( void )
1131 ps_parser_done( PS_Parser parser )
1133 FT_UNUSED( parser );
1137 /*************************************************************************/
1138 /*************************************************************************/
1140 /***** T1 BUILDER *****/
1142 /*************************************************************************/
1143 /*************************************************************************/
1145 /*************************************************************************/
1148 /* t1_builder_init */
1151 /* Initializes a given glyph builder. */
1154 /* builder :: A pointer to the glyph builder to initialize. */
1157 /* face :: The current face object. */
1159 /* size :: The current size object. */
1161 /* glyph :: The current glyph object. */
1163 /* hinting :: Whether hinting should be applied. */
1165 FT_LOCAL_DEF( void )
1166 t1_builder_init( T1_Builder builder,
1172 builder->path_begun = 0;
1173 builder->load_points = 1;
1175 builder->face = face;
1176 builder->glyph = glyph;
1177 builder->memory = face->memory;
1181 FT_GlyphLoader loader = glyph->internal->loader;
1184 builder->loader = loader;
1185 builder->base = &loader->base.outline;
1186 builder->current = &loader->current.outline;
1187 FT_GlyphLoader_Rewind( loader );
1189 builder->hints_globals = size->internal;
1190 builder->hints_funcs = 0;
1193 builder->hints_funcs = glyph->internal->glyph_hints;
1198 builder->scale_x = size->metrics.x_scale;
1199 builder->scale_y = size->metrics.y_scale;
1205 builder->left_bearing.x = 0;
1206 builder->left_bearing.y = 0;
1207 builder->advance.x = 0;
1208 builder->advance.y = 0;
1210 builder->funcs = t1_builder_funcs;
1214 /*************************************************************************/
1217 /* t1_builder_done */
1220 /* Finalizes a given glyph builder. Its contents can still be used */
1221 /* after the call, but the function saves important information */
1222 /* within the corresponding glyph slot. */
1225 /* builder :: A pointer to the glyph builder to finalize. */
1227 FT_LOCAL_DEF( void )
1228 t1_builder_done( T1_Builder builder )
1230 FT_GlyphSlot glyph = builder->glyph;
1234 glyph->outline = *builder->base;
1238 /* check that there is enough space for `count' more points */
1239 FT_LOCAL_DEF( FT_Error )
1240 t1_builder_check_points( T1_Builder builder,
1243 return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
1247 /* add a new point, do not check space */
1248 FT_LOCAL_DEF( void )
1249 t1_builder_add_point( T1_Builder builder,
1254 FT_Outline* outline = builder->current;
1257 if ( builder->load_points )
1259 FT_Vector* point = outline->points + outline->n_points;
1260 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1263 if ( builder->shift )
1270 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1272 builder->last = *point;
1274 outline->n_points++;
1278 /* check space for a new on-curve point, then add it */
1279 FT_LOCAL_DEF( FT_Error )
1280 t1_builder_add_point1( T1_Builder builder,
1287 error = t1_builder_check_points( builder, 1 );
1289 t1_builder_add_point( builder, x, y, 1 );
1295 /* check room for a new contour, then add it */
1296 FT_LOCAL_DEF( FT_Error )
1297 t1_builder_add_contour( T1_Builder builder )
1299 FT_Outline* outline = builder->current;
1303 if ( !builder->load_points )
1305 outline->n_contours++;
1306 return PSaux_Err_Ok;
1309 error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
1312 if ( outline->n_contours > 0 )
1313 outline->contours[outline->n_contours - 1] =
1314 (short)( outline->n_points - 1 );
1316 outline->n_contours++;
1323 /* if a path was begun, add its first on-curve point */
1324 FT_LOCAL_DEF( FT_Error )
1325 t1_builder_start_point( T1_Builder builder,
1332 /* test whether we are building a new contour */
1333 if ( !builder->path_begun )
1335 builder->path_begun = 1;
1336 error = t1_builder_add_contour( builder );
1338 error = t1_builder_add_point1( builder, x, y );
1344 /* close the current contour */
1345 FT_LOCAL_DEF( void )
1346 t1_builder_close_contour( T1_Builder builder )
1348 FT_Outline* outline = builder->current;
1351 /* XXXX: We must not include the last point in the path if it */
1352 /* is located on the first point. */
1353 if ( outline->n_points > 1 )
1356 FT_Vector* p1 = outline->points + first;
1357 FT_Vector* p2 = outline->points + outline->n_points - 1;
1358 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
1361 if ( outline->n_contours > 1 )
1363 first = outline->contours[outline->n_contours - 2] + 1;
1364 p1 = outline->points + first;
1367 /* `delete' last point only if it coincides with the first */
1368 /* point and it is not a control point (which can happen). */
1369 if ( p1->x == p2->x && p1->y == p2->y )
1370 if ( *control == FT_CURVE_TAG_ON )
1371 outline->n_points--;
1374 if ( outline->n_contours > 0 )
1375 outline->contours[outline->n_contours - 1] =
1376 (short)( outline->n_points - 1 );
1380 /*************************************************************************/
1381 /*************************************************************************/
1385 /*************************************************************************/
1386 /*************************************************************************/
1388 FT_LOCAL_DEF( void )
1389 t1_decrypt( FT_Byte* buffer,
1393 while ( length > 0 )
1398 plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
1399 seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );