diff --git a/src/type1z/rules.mk b/src/type1z/rules.mk index d4bc25d11..da2036c3a 100644 --- a/src/type1z/rules.mk +++ b/src/type1z/rules.mk @@ -108,16 +108,16 @@ T1Z_COMPILE := $(FT_COMPILE) $(T1Z_INCLUDE:%=$I%) T1Z_DRV_SRC := $(T1Z_DIR_)t1parse.c \ $(T1Z_DIR_)t1load.c \ $(T1Z_DIR_)t1driver.c \ - $(T1Z_DIR_)t1encode.c \ + $(T1Z_DIR_)t1afm.c \ $(T1Z_DIR_)t1gload.c # Type1 driver headers # T1Z_DRV_H := $(T1Z_DIR_)t1errors.h \ - $(T1Z_DIR_)t1config.h \ - $(T1SHARED_H) \ - $(T1Z_DRV_SRC:%.c=%.h) + $(T1Z_DIR_)t1config.h \ + $(T1SHARED_H) \ + $(T1Z_DRV_SRC:%.c=%.h) # driver object(s) diff --git a/src/type1z/t1afm.c b/src/type1z/t1afm.c new file mode 100644 index 000000000..abd19b8b3 --- /dev/null +++ b/src/type1z/t1afm.c @@ -0,0 +1,222 @@ +/*************************************************************************** + * + * t1afm.c - support for reading Type 1 AFM files + * + * + ***************************************************************************/ + +#include +#include +#include +#include /* for qsort */ + + LOCAL_FUNC + void T1_Done_AFM( FT_Memory memory, T1_AFM* afm ) + { + FREE( afm->kern_pairs ); + afm->num_pairs = 0; + } + +#undef IS_KERN_PAIR +#define IS_KERN_PAIR(p) ( p[0] == 'K' && p[1] == 'P' ) + +#define IS_ALPHANUM(c) ( (c >= 'A' && c <= 'Z') || \ + (c >= 'a' && c <= 'z') || \ + (c >= '0' && c <= '9') || \ + (c == '_' && c == '.') ) + + /* read a glyph name and return the equivalent glyph index */ + static + FT_UInt afm_atoindex( FT_Byte* *start, FT_Byte* limit, T1_Font* type1 ) + { + FT_Byte* p = *start; + FT_Int len; + FT_UInt result = 0; + char temp[64]; + + /* skip whitespace */ + while ( (*p == ' ' || *p == '\t' || *p == ':' || *p == ';') && p < limit ) + p++; + *start = p; + + /* now, read glyph name */ + while ( IS_ALPHANUM(*p) && p < limit ) p++; + len = p - *start; + if (len > 0 && len < 64) + { + FT_Int n; + + /* copy glyph name to intermediate array */ + MEM_Copy( temp, start, len ); + temp[len] = 0; + + /* lookup glyph name in face array */ + for ( n = 0; n < type1->num_glyphs; n++ ) + { + char* gname = (char*)type1->glyph_names; + + if ( gname && gname[0] == temp[0] && strcmp(gname,temp) == 0 ) + { + result = n; + break; + } + } + } + *start = p; + return result; + } + + + /* read an integer */ + static + int afm_atoi( FT_Byte** start, FT_Byte* limit ) + { + FT_Byte* p = *start; + int sum = 0; + + /* skip everything that is not a number */ + while ( p < limit && (*p < '0' || *p > '9') ) + p++; + + while ( p < limit && (*p >= '0' || *p < '9') ) + { + sum = sum*10 + (*p - '0'); + p++; + } + *start = p; + return sum; + } + + +#undef KERN_INDEX +#define KERN_INDEX(g1,g2) (((T1_ULong)g1 << 16) | g2) + + /* compare two kerning pairs */ + static + int compare_kern_pairs( const void* a, const void* b ) + { + T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a; + T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b; + + T1_ULong index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2); + T1_ULong index2 = KERN_INDEX(pair2->glyph1,pair2->glyph2); + + return ( index1 < index2 ? -1 : + ( index1 > index2 ? 1 : 0 )); + } + + + /* parse an AFM file - for now, only read the kerning pairs */ + LOCAL_FUNC + FT_Error T1_Read_AFM( FT_Stream stream, + FT_Face t1_face ) + { + FT_Error error; + FT_Memory memory = stream->memory; + FT_Byte* start; + FT_Byte* limit; + FT_Byte* p; + FT_Int count = 0; + T1_Kern_Pair* pair; + T1_Font* type1 = &((T1_Face)t1_face)->type1; + T1_AFM* afm = 0; + + if ( !ACCESS_Frame(stream->size) ) + return error; + + start = (FT_Byte*)stream->cursor; + limit = (FT_Byte*)stream->limit; + p = start; + + /* we are now going to count the occurences of "KP" or "KPX" in */ + /* the AFM file.. */ + count = 0; + for ( p = start; p < limit-3; p++ ) + { + if ( IS_KERN_PAIR(p) ) + count++; + } + + /* Actually, kerning pairs are simply optional !! */ + if (count == 0) + goto Exit; + + /* allocate the pairs */ + if ( ALLOC( afm, sizeof(*afm ) ) || + ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) ) + goto Exit; + + /* now, read each kern pair */ + pair = afm->kern_pairs; + afm->num_pairs = count; + + /* save in face object */ + ((T1_Face)t1_face)->afm_data = afm; + + for ( p = start; p < limit-3; p++ ) + { + if ( IS_KERN_PAIR(p) ) + { + FT_Byte* q; + + /* skip keyword (KP or KPX) */ + q = p+2; + if (*q == 'X') q++; + + pair->glyph1 = afm_atoindex( &q, limit, type1 ); + pair->glyph2 = afm_atoindex( &q, limit, type1 ); + pair->kerning.x = afm_atoi( &q, limit ); + + pair->kerning.y = 0; + if ( p[2] != 'X' ) + pair->kerning.y = afm_atoi( &q, limit ); + + pair++; + } + } + + /* now, sort the kern pairs according to their glyph indices */ + qsort( afm->kern_pairs, count, sizeof(T1_Kern_Pair), compare_kern_pairs ); + + Exit: + if (error) + FREE( afm ); + + FORGET_Frame(); + return error; + } + + + /* find the kerning for a given glyph pair */ + LOCAL_FUNC + void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ) + { + T1_Kern_Pair *min, *mid, *max; + T1_ULong index = KERN_INDEX(glyph1,glyph2); + + /* simple binary search */ + min = afm->kern_pairs; + max = min + afm->num_pairs-1; + + while (min <= max) + { + T1_ULong midi; + + mid = min + (max-min)/2; + midi = KERN_INDEX(mid->glyph1,mid->glyph2); + if ( midi == index ) + { + *kerning = mid->kerning; + return; + } + + if ( midi < index ) min = mid+1; + else max = mid-1; + } + kerning->x = 0; + kerning->y = 0; + } + diff --git a/src/type1z/t1afm.h b/src/type1z/t1afm.h new file mode 100644 index 000000000..39bbc4bea --- /dev/null +++ b/src/type1z/t1afm.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * + * t1afm.h - support for reading Type 1 AFM files + * + * + ***************************************************************************/ + +#ifndef T1AFM_H +#define T1AFM_H + +#include + +/* In this version, we only read the kerning table from the */ +/* AFM file. We may add support for ligatures a bit later.. */ + +typedef struct T1_Kern_Pair_ +{ + FT_UInt glyph1; + FT_UInt glyph2; + FT_Vector kerning; + +} T1_Kern_Pair; + + +typedef struct T1_AFM_ +{ + FT_Int num_pairs; + T1_Kern_Pair* kern_pairs; + +} T1_AFM; + + +LOCAL_DEF +FT_Error T1_Read_AFM( FT_Stream stream, + FT_Face face ); + +LOCAL_DEF +void T1_Done_AFM( FT_Memory memory, + T1_AFM* afm ); + +LOCAL_DEF +void T1_Get_Kerning( T1_AFM* afm, + FT_UInt glyph1, + FT_UInt glyph2, + FT_Vector* kerning ); + +#endif /* T1AFM_H */ diff --git a/src/type1z/t1config.h b/src/type1z/t1config.h index a72b177b2..9767301f9 100644 --- a/src/type1z/t1config.h +++ b/src/type1z/t1config.h @@ -42,4 +42,11 @@ /* */ #undef T1_CONFIG_OPTION_DISABLE_HINTER +/* Define this configuration macro if you want to prevent the */ +/* compilation of "t1afm", which is in charge of reading Type1 */ +/* AFM files into an existing face. Note that when set, the T1 */ +/* driver will be unable to produce kerning distances.. */ +/* */ +#undef T1_CONFIG_OPTION_NO_AFM + #endif /* T1CONFIG_H */ diff --git a/src/type1z/t1driver.c b/src/type1z/t1driver.c index 039ecd118..9d2fdd982 100644 --- a/src/type1z/t1driver.c +++ b/src/type1z/t1driver.c @@ -17,13 +17,16 @@ #include #include +#include #include #include +#include #undef FT_COMPONENT #define FT_COMPONENT trace_t1driver +#ifndef T1_CONFIG_OPTION_NO_AFM /*************************************************************************/ /* */ /* */ @@ -52,15 +55,68 @@ /* time). */ /* */ static - void* Get_Interface( FT_Driver* driver, - const FT_String* interface ) + FTDriver_Interface Get_Interface( FT_Driver driver, + const FT_String* interface ) { - UNUSED(driver); - UNUSED(interface); + if ( strcmp( (const char*)interface, "attach_file" ) == 0 ) + return (FTDriver_Interface)T1_Read_AFM; + return 0; } + + /*************************************************************************/ + /* */ + /* */ + /* Get_Kerning */ + /* */ + /* */ + /* A driver method used to return the kerning vector between two */ + /* glyphs of the same face. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* left_glyph :: The index of the left glyph in the kern pair. */ + /* */ + /* right_glyph :: The index of the right glyph in the kern pair. */ + /* */ + /* */ + /* kerning :: The kerning vector. This is in font units for */ + /* scalable formats, and in pixels for fixed-sizes */ + /* formats. */ + /* */ + /* */ + /* FreeType error code. 0 means success. */ + /* */ + /* */ + /* Only horizontal layouts (left-to-right & right-to-left) are */ + /* supported by this function. Other layouts, or more sophisticated */ + /* kernings are out of scope of this method (the basic driver */ + /* interface is meant to be simple). */ + /* */ + /* They can be implemented by format-specific interfaces. */ + /* */ + static + T1_Error Get_Kerning( T1_Face face, + T1_UInt left_glyph, + T1_UInt right_glyph, + T1_Vector* kerning ) + { + T1_AFM* afm; + + kerning->x = 0; + kerning->y = 0; + + afm = (T1_AFM*)face->afm_data; + if (afm) + T1_Get_Kerning( afm, left_glyph, right_glyph, kerning ); + + return T1_Err_Ok; + } +#endif + /******************************************************************/ /* */ /* Set_Char_Sizes */ @@ -130,6 +186,171 @@ return T1_Reset_Size(size); } + /*************************************************************************/ + /* */ + /* */ + /* Get_Char_Index */ + /* */ + /* */ + /* Uses a charmap to return a given character code's glyph index. */ + /* */ + /* */ + /* charmap :: A handle to the source charmap object. */ + /* charcode :: The character code. */ + /* */ + /* */ + /* Glyph index. 0 means `undefined character code'. */ + /* */ + static + T1_UInt Get_Char_Index( FT_CharMap charmap, + T1_Long charcode ) + { + T1_Face face; + T1_UInt result = 0; + PSNames_Interface* psnames; + + face = (T1_Face)charmap->face; + psnames = (PSNames_Interface*)face->psnames; + if (psnames) + switch (charmap->encoding) + { + /********************************************************************/ + /* */ + /* Unicode encoding support */ + /* */ + case ft_encoding_unicode: + { + /* use the "psnames" module to synthetize the Unicode charmap */ + result = psnames->lookup_unicode( &face->unicode_map, + (T1_ULong)charcode ); + + /* the function returns 0xFFFF when the Unicode charcode has */ + /* no corresponding glyph.. */ + if (result == 0xFFFF) + result = 0; + goto Exit; + } + + /********************************************************************/ + /* */ + /* Custom Type 1 encoding */ + /* */ + case ft_encoding_adobe_custom: + { + T1_Encoding* encoding = &face->type1.encoding; + if (charcode >= encoding->code_first && + charcode <= encoding->code_last) + { + result = encoding->char_index[charcode]; + } + goto Exit; + } + + /********************************************************************/ + /* */ + /* Adobe Standard & Expert encoding support */ + /* */ + default: + if (charcode < 256) + { + FT_UInt code; + FT_Int n; + const char* glyph_name; + + code = psnames->adobe_std_encoding[charcode]; + if (charmap->encoding == ft_encoding_adobe_expert) + code = psnames->adobe_expert_encoding[charcode]; + + glyph_name = psnames->adobe_std_strings(code); + if (!glyph_name) break; + + for ( n = 0; n < face->type1.num_glyphs; n++ ) + { + const char* gname = face->type1.glyph_names[n]; + + if ( gname && gname[0] == glyph_name[0] && + strcmp( gname, glyph_name ) == 0 ) + { + result = n; + break; + } + } + } + } + Exit: + return result; + } + + + static + T1_Error Init_Face( FT_Stream stream, + FT_Int face_index, + T1_Face face ) + { + T1_Error error; + + error = T1_Init_Face(stream, face_index, face); + if (!error) + { + FT_Face root = &face->root; + FT_CharMap charmap = face->charmaprecs; + + /* synthetize a Unicode charmap if there is support in the "psnames" */ + /* module.. */ + if (face->psnames) + { + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; + if (psnames->unicode_value) + { + error = psnames->build_unicodes( root->memory, + face->type1.num_glyphs, + (const char**)face->type1.glyph_names, + &face->unicode_map ); + if (!error) + { + root->charmap = charmap; + charmap->face = (FT_Face)face; + charmap->encoding = ft_encoding_unicode; + charmap->platform_id = 3; + charmap->encoding_id = 1; + charmap++; + } + + /* simply clear the error in case of failure (which really) */ + /* means that out of memory or no unicode glyph names */ + error = 0; + } + } + + /* now, support either the standard, expert, or custom encodings */ + charmap->face = (FT_Face)face; + charmap->platform_id = 7; /* a new platform id for Adobe fonts ?? */ + + switch (face->type1.encoding_type) + { + case t1_encoding_standard: + charmap->encoding = ft_encoding_adobe_standard; + charmap->encoding_id = 0; + break; + + case t1_encoding_expert: + charmap->encoding = ft_encoding_adobe_expert; + charmap->encoding_id = 1; + break; + + default: + charmap->encoding = ft_encoding_adobe_custom; + charmap->encoding_id = 2; + break; + } + + root->charmaps = face->charmaps; + root->num_charmaps = charmap - face->charmaprecs + 1; + face->charmaps[0] = &face->charmaprecs[0]; + face->charmaps[1] = &face->charmaprecs[1]; + } + return error; + } /******************************************************************/ /* */ @@ -206,7 +427,7 @@ /* */ EXPORT_FUNC - const FT_DriverInterface t1_driver_interface = + const FT_DriverInterface t1z_driver_interface = { sizeof( FT_DriverRec ), sizeof( T1_FaceRec ), @@ -214,18 +435,28 @@ sizeof( T1_GlyphSlotRec ), "type1", - 100, /* driver version == 1.0 */ - 200, /* requires FreeType 2.0 or above */ + 100, + 200, 0, /* format interface */ (FTDriver_initDriver) T1_Init_Driver, (FTDriver_doneDriver) T1_Done_Driver, - (FTDriver_getInterface) Get_Interface, - (FTDriver_initFace) T1_Init_Face, +#ifdef T1_CONFIG_OPTION_NO_AFM + (FTDriver_getInterface) 0, +#else + (FTDriver_getInterface) Get_Interface, +#endif + + (FTDriver_initFace) Init_Face, (FTDriver_doneFace) T1_Done_Face, + +#ifdef T1_CONFIG_OPTION_NO_AFM (FTDriver_getKerning) 0, +#else + (FTDriver_getKerning) Get_Kerning, +#endif (FTDriver_initSize) T1_Init_Size, (FTDriver_doneSize) T1_Done_Size, @@ -236,36 +467,38 @@ (FTDriver_doneGlyphSlot) T1_Done_GlyphSlot, (FTDriver_loadGlyph) T1_Load_Glyph, - (FTDriver_getCharIndex) 0, + (FTDriver_getCharIndex) Get_Char_Index, }; - /*************************************************************************/ - /* */ - /* */ - /* getDriverInterface */ - /* */ - /* */ - /* This function is used when compiling the font driver as a */ - /* shared library (`.DLL' or `.so'). It will be used by the */ - /* high-level library of FreeType to retrieve the address of the */ - /* driver's generic interface. */ - /* */ - /* It shouldn't be implemented in a static build, as each driver must */ - /* have the same function as an exported entry point. */ - /* */ - /* */ - /* The address of the TrueType's driver generic interface. The */ - /* format-specific interface can then be retrieved through the method */ - /* interface->get_format_interface. */ - /* */ -#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + /******************************************************************/ + /* */ + /* Get_FreeType_Driver_Interface */ + /* */ + /* */ + /* This function is used when compiling the TrueType driver */ + /* as a shared library (.DLL or .so). It will be used by the */ + /* high-level library of FreeType to retrieve the address of */ + /* the driver's generic interface. */ + /* */ + /* It shouldn't be implemented in a static build, as each */ + /* driver must have the same function as an exported entry */ + /* point. */ + /* */ + /* */ + /* address of TrueType's driver generic interface. The */ + /* forma-specific interface can then be retrieved through */ + /* the method interface->get_format_interface.. */ + /* */ + +#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS + EXPORT_FUNC FT_DriverInterface* getDriverInterface( void ) { return &t1_driver_interface; } - -#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ + +#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */ diff --git a/src/type1z/t1driver.h b/src/type1z/t1driver.h index a442035c3..801fc5474 100644 --- a/src/type1z/t1driver.h +++ b/src/type1z/t1driver.h @@ -22,7 +22,7 @@ #include EXPORT_DEF - const FT_DriverInterface t1_driver_interface; + const FT_DriverInterface t1z_driver_interface; #endif /* T1DRIVER_H */ diff --git a/src/type1z/t1gload.c b/src/type1z/t1gload.c index 0b1d8f4f5..476b6183f 100644 --- a/src/type1z/t1gload.c +++ b/src/type1z/t1gload.c @@ -17,9 +17,75 @@ #include #include -#include #include +#undef FT_COMPONENT +#define FT_COMPONENT trace_t1gload + + typedef enum T1_Operator_ + { + op_none = 0, + op_endchar, + op_hsbw, + op_seac, + op_sbw, + op_closepath, + op_hlineto, + op_hmoveto, + op_hvcurveto, + op_rlineto, + op_rmoveto, + op_rrcurveto, + op_vhcurveto, + op_vlineto, + op_vmoveto, + op_dotsection, + op_hstem, + op_hstem3, + op_vstem, + op_vstem3, + op_div, + op_callothersubr, + op_callsubr, + op_pop, + op_return, + op_setcurrentpoint, + + op_max /* never remove this one */ + + } T1_Operator; + + static const T1_Int t1_args_count[ op_max ] = + { + 0, /* none */ + 0, /* endchar */ + 2, /* hsbw */ + 5, /* seac */ + 4, /* sbw */ + 0, /* closepath */ + 1, /* hlineto */ + 1, /* hmoveto */ + 4, /* hvcurveto */ + 2, /* rlineto */ + 2, /* rmoveto */ + 6, /* rrcurveto */ + 4, /* vhcurveto */ + 1, /* vlineto */ + 1, /* vmoveto */ + 0, /* dotsection */ + 2, /* hstem */ + 6, /* hstem3 */ + 2, /* vstem */ + 6, /* vstem3 */ + 2, /* div */ + -1, /* callothersubr */ + 1, /* callsubr */ + 0, /* pop */ + 0, /* return */ + 2 /* setcurrentpoint */ + }; + + /**********************************************************************/ /**********************************************************************/ /**********************************************************************/ @@ -264,17 +330,26 @@ if (outline->n_contours > 0) outline->contours[ outline->n_contours-1 ] = outline->n_points-1; + outline->n_contours++; return T1_Err_Ok; } - /* if a path was begun, add its first on-curve point */ static T1_Error start_point( T1_Builder* builder, T1_Pos x, T1_Pos y ) { - return builder->path_begun && add_point1( builder, x, y ); + /* test wether we're building a new contour */ + if (!builder->path_begun) + { + T1_Error error; + + builder->path_begun = 1; + error = add_contour( builder ); + if (error) return error; + } + return add_point1( builder, x, y ); } @@ -312,20 +387,22 @@ T1_Int lookup_glyph_by_stdcharcode( T1_Face face, T1_Int charcode ) { - T1_Int n; - const T1_String* glyph_name; + T1_Int n; + const T1_String* glyph_name; + PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; /* check range of standard char code */ if (charcode < 0 || charcode > 255) return -1; - glyph_name = t1_standard_strings[t1_standard_encoding[charcode]]; + glyph_name = psnames->adobe_std_strings( + psnames->adobe_std_encoding[charcode]); for ( n = 0; n < face->type1.num_glyphs; n++ ) { T1_String* name = (T1_String*)face->type1.glyph_names[n]; - if ( name && name[0] == glyph_name[0] && strcmp(name,glyph_name) == 0 ) + if ( name && strcmp(name,glyph_name) == 0 ) return n; } @@ -506,62 +583,364 @@ while ( ip < limit ) { T1_Int* top = decoder->top; + T1_Operator op = op_none; + T1_Long value = 0; + + /********************************************************************/ + /* */ + /* Decode operator or operand */ + /* */ + /* */ /* First of all, decompress operator or value */ switch (*ip++) { - case 1: /* hstem */ - case 3: /* vstem */ + case 1: op = op_hstem; break; + + case 3: op = op_vstem; break; + case 4: op = op_vmoveto; break; + case 5: op = op_rlineto; break; + case 6: op = op_hlineto; break; + case 7: op = op_vlineto; break; + case 8: op = op_rrcurveto; break; + case 9: op = op_closepath; break; + case 10: op = op_callsubr; break; + case 11: op = op_return; break; + + case 13: op = op_hsbw; break; + case 14: op = op_endchar; break; + + case 21: op = op_rmoveto; break; + case 22: op = op_hmoveto; break; + + case 30: op = op_vhcurveto; break; + case 31: op = op_hvcurveto; break; + + case 12: { - Clear_Stack: - top = decoder->stack; + if (ip > limit) + { + FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" )); + goto Syntax_Error; + } + + switch (*ip++) + { + case 0: op = op_dotsection; break; + case 1: op = op_vstem3; break; + case 2: op = op_hstem3; break; + case 6: op = op_seac; break; + case 7: op = op_sbw; break; + case 12: op = op_div; break; + case 16: op = op_callothersubr; break; + case 17: op = op_pop; break; + case 33: op = op_setcurrentpoint; break; + + default: + FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + break; + + case 255: /* four bytes integer */ + { + if (ip+4 > limit) + { + FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + value = ((long)ip[0] << 24) | + ((long)ip[1] << 16) | + ((long)ip[2] << 8) | + ip[3]; + ip += 4; + } + break; + + default: + if (ip[-1] >= 32) + { + if (ip[-1] < 247) + value = (long)ip[-1] - 139; + else + { + if (++ip > limit) + { + FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" )); + goto Syntax_Error; + } + + if (ip[-2] < 251) + value = ((long)(ip[-2]-247) << 8) + ip[-1] + 108; + else + value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 ); + } + } + else + { + FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n", + ip[-1] )); + goto Syntax_Error; + } + } + + /********************************************************************/ + /* */ + /* Push value on stack, or process operator */ + /* */ + /* */ + if ( op == op_none ) + { + if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) + { + FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" )); + goto Syntax_Error; + } + + FT_TRACE4(( " %ld", value )); + *top++ = value; + decoder->top = top; + } + else if ( op == op_callothersubr ) /* callothersubr */ + { + FT_TRACE4(( " callothersubr" )); + if ( top - decoder->stack < 2 ) + goto Stack_Underflow; + + top -= 2; + switch ( top[1] ) + { + case 1: /* start flex feature ---------------------- */ + { + if ( top[0] != 0 ) goto Unexpected_OtherSubr; + + decoder->flex_state = 1; + decoder->num_flex_vectors = 0; + if ( start_point(builder, x, y) || + check_points(builder,6) ) goto Memory_Error; + } + break; + + case 2: /* add flex vectors ------------------------ */ + { + T1_Int index; + + if ( top[0] != 0 ) goto Unexpected_OtherSubr; + + /* note that we should not add a point for index 0 */ + /* this will move our current position to the flex */ + /* point without adding any point to the outline */ + index = decoder->num_flex_vectors++; + if (index > 0 && index < 7) + add_point( builder, + x, + y, + (T1_Byte)( index==3 || index==6 ) ); + } + break; + + case 0: /* end flex feature ------------------------- */ + { + if ( top[0] != 3 ) goto Unexpected_OtherSubr; + + if ( decoder->flex_state == 0 || + decoder->num_flex_vectors != 7 ) + { + FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" )); + goto Syntax_Error; + } + + /* now consume the remaining "pop pop setcurpoint" */ + if ( ip+6 > limit || + ip[0] != 12 || ip[1] != 17 || /* pop */ + ip[2] != 12 || ip[3] != 17 || /* pop */ + ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ + { + FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" )); + goto Syntax_Error; + } + + ip += 6; + decoder->flex_state = 0; + break; + } + + case 3: /* change hints ---------------------------- */ + { + if ( top[0] != 1 ) goto Unexpected_OtherSubr; + + /* eat the following "pop" */ + if (ip+2 > limit) + { + FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n", + ip[-1] )); + goto Syntax_Error; + } + + if (ip[0] != 12 || ip[1] != 17) + { + FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n", + ip[0], ip[1] )); + goto Syntax_Error; + } + ip += 2; + break;; + } + + default: + Unexpected_OtherSubr: + FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr [%d %d]!!\n", + top[0], top[1] )); + goto Syntax_Error; + } + decoder->top = top; + } + else /* general operator */ + { + T1_Int num_args = t1_args_count[op]; + + if ( top - decoder->stack < num_args ) + goto Stack_Underflow; + + top -= num_args; + + switch (op) + { + case op_endchar: /*************************************************/ + { + FT_TRACE4(( " endchar" )); + close_contour( builder ); + + /* add current outline to the glyph slot */ + builder->base.n_points += builder->current.n_points; + builder->base.n_contours += builder->current.n_contours; + + /* return now !! */ + FT_TRACE4(( "\n\n" )); + return T1_Err_Ok; + } + + + case op_hsbw: /****************************************************/ + { + FT_TRACE4(( " hsbw" )); + builder->left_bearing.x += top[0]; + builder->advance.x = top[1]; + builder->advance.y = 0; + + builder->last.x = x = top[0]; + builder->last.y = y = 0; + + /* the "metrics_only" indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it.. so exit immediately */ + if (builder->metrics_only) + return T1_Err_Ok; + break; } - case 4: /* vmoveto */ + + case op_seac: /****************************************************/ + /* return immediately after the processing */ + return t1operator_seac( decoder, top[0], top[1], + top[2], top[3], top[4] ); + + case op_sbw: /****************************************************/ { - USE_ARGS(1); - y += top[0]; - builder->path_begun = 1; - goto Clear_Stack; + FT_TRACE4(( " sbw" )); + builder->left_bearing.x += top[0]; + builder->left_bearing.y += top[1]; + builder->advance.x = top[2]; + builder->advance.y = top[3]; + + builder->last.x = x = top[0]; + builder->last.y = y = top[1]; + + /* the "metrics_only" indicates that we only want to compute */ + /* the glyph's metrics (lsb + advance width), not load the */ + /* rest of it.. so exit immediately */ + if (builder->metrics_only) + return T1_Err_Ok; + + break; } - - case 5: /* rlineto */ + + + case op_closepath: /**********************************************/ { + FT_TRACE4(( " closepath" )); + close_contour( builder ); + builder->path_begun = 0; + } + break; + + + case op_hlineto: /************************************************/ + { + FT_TRACE4(( " hlineto" )); + if ( start_point( builder, x, y ) ) goto Memory_Error; + + x += top[0]; + goto Add_Line; + } + + + case op_hmoveto: /************************************************/ + { + FT_TRACE4(( " hmoveto" )); + x += top[0]; + break; + } + + + case op_hvcurveto: /**********************************************/ + { + FT_TRACE4(( " hvcurveto" )); + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) goto Memory_Error; + + x += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + y += top[3]; + add_point( builder, x, y, 1 ); + break; + } + + + case op_rlineto: /*************************************************/ + { + FT_TRACE4(( " rlineto" )); if ( start_point( builder, x, y ) ) goto Memory_Error; - USE_ARGS(2); x += top[0]; y += top[1]; Add_Line: - if (add_point1( builder, top[0], top[1] )) goto Memory_Error; - goto Clear_Stack; + if (add_point1( builder, x, y )) goto Memory_Error; + break; } - - case 6: /* hlineto */ + + + case op_rmoveto: /*************************************************/ { - if ( start_point( builder, x, y ) ) goto Memory_Error; - - USE_ARGS(1); + FT_TRACE4(( " rmoveto" )); x += top[0]; - goto Add_Line; + y += top[1]; + break; } - - case 7: /* vlineto */ - { - if ( start_point( builder, x, y ) ) goto Memory_Error; - - USE_ARGS(1); - y += top[0]; - goto Add_Line; - } - - case 8: /* rrcurveto */ + + case op_rrcurveto: /***********************************************/ { + FT_TRACE4(( " rcurveto" )); if ( start_point( builder, x, y ) || check_points( builder, 3 ) ) goto Memory_Error; - USE_ARGS(6); x += top[0]; y += top[1]; add_point( builder, x, y, 0 ); @@ -573,22 +952,64 @@ x += top[4]; y += top[5]; add_point( builder, x, y, 1 ); - goto Clear_Stack; + break; } - - case 9: /* closepath */ + + + case op_vhcurveto: /**********************************************/ { - close_contour( builder ); - builder->path_begun = 0; + FT_TRACE4(( " vhcurveto" )); + if ( start_point( builder, x, y ) || + check_points( builder, 3 ) ) goto Memory_Error; + + y += top[0]; + add_point( builder, x, y, 0 ); + x += top[1]; + y += top[2]; + add_point( builder, x, y, 0 ); + x += top[3]; + add_point( builder, x, y, 1 ); + break; } - break; - - case 10: /* callsubr */ + + + case op_vlineto: /************************************************/ + { + FT_TRACE4(( " vlineto" )); + if ( start_point( builder, x, y ) ) goto Memory_Error; + + y += top[0]; + goto Add_Line; + } + + + case op_vmoveto: /************************************************/ + { + FT_TRACE4(( " vmoveto" )); + y += top[0]; + break; + } + + + case op_div: /****************************************************/ + { + FT_TRACE4(( " div" )); + if (top[1]) + *top++ = top[0] / top[1]; + else + { + FT_ERROR(( "T1.Parse_CharStrings : division by 0\n" )); + goto Syntax_Error; + } + break; + } + + + case op_callsubr: /***********************************************/ { T1_Int index; - USE_ARGS(1); - + FT_TRACE4(( " callsubr" )); index = top[0]; if ( index < 0 || index >= num_subrs ) { @@ -618,13 +1039,21 @@ decoder->zone = zone; ip = zone->base; limit = zone->limit; - - /* do not clear stack */ + break; } - break; - - case 11: /* return */ + + + case op_pop: /****************************************************/ { + FT_TRACE4(( " pop" )); + FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" )); + goto Syntax_Error; + } + + + case op_return: /************************************************/ + { + FT_TRACE4(( " return" )); if ( zone <= decoder->zones ) { FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" )); @@ -635,306 +1064,58 @@ ip = zone->cursor; limit = zone->limit; decoder->zone = zone; + break; } - break; - - case 13: /* hsbw */ + + case op_dotsection: /*********************************************/ { - USE_ARGS(2); - builder->left_bearing.x += top[0]; - builder->advance.x = top[1]; - builder->advance.y = 0; - - builder->last.x = x = top[0]; - builder->last.y = y = 0; - - /* the "metrics_only" indicates that we only want to compute */ - /* the glyph's metrics (lsb + advance width), not load the */ - /* rest of it.. so exit immediately */ - if (builder->metrics_only) - return T1_Err_Ok; - - goto Clear_Stack; + FT_TRACE4(( " dotsection" )); + break; } - case 14: /* endchar */ + case op_hstem: /**************************************************/ { - close_contour( builder ); - - /* add current outline to the glyph slot */ - builder->base.n_points += builder->current.n_points; - builder->base.n_contours += builder->current.n_contours; - - /* return now !! */ - return T1_Err_Ok; + FT_TRACE4(( " hstem" )); + break; } - - case 21: /* rmoveto */ + + case op_hstem3: /*************************************************/ { - USE_ARGS(2); - x += top[0]; - y += top[1]; - goto Clear_Stack; + FT_TRACE4(( " hstem3" )); + break; } - - case 22: /* hmoveto */ + + case op_vstem: /**************************************************/ { - USE_ARGS(1); - x += top[0]; - goto Clear_Stack; + FT_TRACE4(( " vstem" )); + break; } - - case 30: /* vhcurveto */ + + case op_vstem3: /*************************************************/ { - if ( start_point( builder, x, y ) || - check_points( builder, 3 ) ) goto Memory_Error; - - USE_ARGS(4); - y += top[0]; - add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; - add_point( builder, x, y, 0 ); - x += top[3]; - add_point( builder, x, y, 1 ); - goto Clear_Stack; + FT_TRACE4(( " vstem3" )); + break; } - - case 31: /* hvcurveto */ + + case op_setcurrentpoint: /*****************************************/ { - if ( start_point( builder, x, y ) || - check_points( builder, 3 ) ) goto Memory_Error; - - USE_ARGS(4); - x += top[0]; - add_point( builder, x, y, 0 ); - x += top[1]; - y += top[2]; - add_point( builder, x, y, 0 ); - y += top[3]; - add_point( builder, x, y, 1 ); - goto Clear_Stack; + FT_TRACE4(( " setcurrentpoint" )); + FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" )); + goto Syntax_Error; } - - case 12: - { - if (ip > limit) - { - FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" )); - goto Syntax_Error; - } + default: + FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op )); + goto Syntax_Error; + } - switch (*ip++) - { - case 0: /* dotsection */ - case 1: /* vstem3 */ - case 2: /* hstem3 */ - goto Clear_Stack; - - case 6: /* seac */ - { - USE_ARGS(5); - - /* return immediately to implement an accented character */ - return t1operator_seac( decoder, - top[0], top[1], top[3], - top[4], top[5] ); - } - - case 7: /* sbw */ - { - USE_ARGS(4); - builder->left_bearing.x += top[0]; - builder->left_bearing.y += top[1]; - builder->advance.x = top[2]; - builder->advance.y = top[3]; - - builder->last.x = x = top[0]; - builder->last.y = y = top[1]; - - /* the "metrics_only" indicates that we only want to compute */ - /* the glyph's metrics (lsb + advance width), not load the */ - /* rest of it.. so exit immediately */ - if (builder->metrics_only) - return T1_Err_Ok; - - goto Clear_Stack; - } - - case 12: /* div */ - { - USE_ARGS(2); - top[0] /= top[1]; - top++; - } - break; - - case 16: /* callothersubr */ - { - USE_ARGS(1); - switch (top[0]) - { - case 1: /* start flex feature ---------------------- */ - { - decoder->flex_state = 1; - decoder->num_flex_vectors = 0; - if ( start_point(builder, x, y) || - check_points(builder,6) ) goto Memory_Error; - } - break; + decoder->top = top; + + } /* general operator processing */ - case 2: /* add flex vectors ------------------------ */ - { - T1_Int index; - - /* note that we should not add a point for index 0 */ - /* this will move our current position to the flex */ - /* point without adding any point to the outline */ - index = decoder->num_flex_vectors++; - if (index > 0 && index < 7) - add_point( builder, - x, - y, - (T1_Byte)( index==3 || index==6 ) ); - } - break; - - case 0: /* end flex feature ------------------------- */ - { - USE_ARGS(3); /* ignore parameters */ - - if ( decoder->flex_state == 0 || - decoder->num_flex_vectors != 7 ) - { - FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" )); - goto Syntax_Error; - } - - /* now consume the remaining "pop pop setcurpoint" */ - if ( ip+6 > limit || - ip[0] != 12 || ip[1] != 17 || /* pop */ - ip[2] != 12 || ip[3] != 17 || /* pop */ - ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */ - { - FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" )); - goto Syntax_Error; - } - - ip += 6; - decoder->flex_state = 0; - decoder->top = top; - - goto Clear_Stack; - } - - case 3: /* change hints ---------------------------- */ - { - /* eat the following "pop" */ - if (ip+2 > limit) - { - FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n", - ip[-1] )); - goto Syntax_Error; - } - - if (ip[0] != 12 || ip[1] != 17) - { - FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n", - ip[0], ip[1] )); - goto Syntax_Error; - } - ip += 2; - goto Clear_Stack; - } - - default: - FT_ERROR(( "T1.Parse_CharStrings: invalid othersubr %d !!\n", - top[0] )); - goto Syntax_Error; - } - } - - case 17: /* pop - should not happen !! */ - { - FT_ERROR(( "T1.Parse_CharStrings : 'pop' should not happen !!\n" )); - goto Syntax_Error; - } - - case 33: /* setcurrentpoint */ - { - FT_ERROR(( "T1.Parse_CharStrings : 'setcurrentpoint' should not happen !!\n" )); - goto Syntax_Error; - } - - default: - FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n", - ip[-1] )); - goto Syntax_Error; - } - } - break; /* escape - 12 */ - - case 255: /* four bytes integer */ - { - if (ip+4 > limit) - { - FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" )); - goto Syntax_Error; - } - - *top++ = ((long)ip[0] << 24) | - ((long)ip[1] << 16) | - ((long)ip[2] << 8) | - ip[3]; - ip += 4; - } - break; - - default: - { - T1_Long v, v2; - - v = ip[-1]; - if (v < 32) - { - FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n", - ip[-1] )); - goto Syntax_Error; - } - - /* compute value ---- */ - /* */ - if (v < 247) /* 1-byte value */ - v -= 139; - else - { - if (++ip > limit) /* 2-bytes value, check limits */ - { - FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" )); - goto Syntax_Error; - } - - v2 = ip[-1] + 108; - if (v < 251) - v = ((v-247) << 8) + v2; - else - v = -(((v-251) << 8) + v2); - } - - /* store value - is there enough room ?*/ - if ( top >= decoder->stack + T1_MAX_CHARSTRINGS_OPERANDS ) - { - FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" )); - goto Syntax_Error; - } - - *top++ = v; - decoder->top = top; - } - } /* big switch */ } /* while ip < limit */ + FT_TRACE4(( "..end..\n\n" )); return error; Syntax_Error: diff --git a/src/type1z/t1load.c b/src/type1z/t1load.c index 2bf4ec435..9795031a3 100644 --- a/src/type1z/t1load.c +++ b/src/type1z/t1load.c @@ -63,10 +63,8 @@ #include #include -#include #include #include - #include #undef FT_COMPONENT @@ -345,8 +343,12 @@ { if ( cur[1] == 'e' && cur[2] == 'f' && + is_space(cur[-1]) && is_space(cur[3]) ) - break; + { + FT_TRACE6(( "encoding end\n" )); + break; + } } /* otherwise, we must find a number before anything else */ @@ -382,6 +384,7 @@ } face->type1.encoding_type = t1_encoding_array; + parser->cursor = cur; } /* Otherwise, we should have either "StandardEncoding" or */ /* "ExpertEncoding" */ @@ -433,6 +436,10 @@ index = T1_ToInt(parser); if (!read_binary_data(parser,&size,&base)) return; + T1_Decrypt( base, size, 4330 ); + size -= face->type1.lenIV; + base += face->type1.lenIV; + error = T1_Add_Table( table, index, base, size ); if (error) goto Fail; } @@ -481,13 +488,19 @@ cur = parser->cursor; if (cur >= limit) break; - /* we stop when we find a "def" */ + /* we stop when we find a "def" or "end" keyword */ if (*cur == 'd' && cur+3 < limit && cur[1] == 'e' && cur[2] == 'f' ) break; + if (*cur == 'e' && + cur+3 < limit && + cur[1] == 'n' && + cur[2] == 'd' ) + break; + if (*cur != '/') skip_blackspace(parser); else @@ -497,6 +510,7 @@ while (cur2 < limit && is_alpha(*cur2)) cur2++; len = cur2-cur-1; + error = T1_Add_Table( name_table, n, cur+1, len+1 ); if (error) goto Fail; @@ -505,7 +519,11 @@ parser->cursor = cur2; if (!read_binary_data(parser,&size,&base)) return; - + + T1_Decrypt( base, size, 4330 ); + size -= face->type1.lenIV; + base += face->type1.lenIV; + error = T1_Add_Table( code_table, n, base, size ); if (error) goto Fail; @@ -514,6 +532,7 @@ break; } } + loader->num_glyphs = n; return; Fail: @@ -562,7 +581,7 @@ T1_Error parse_dict( T1_Face face, T1_Loader* loader, T1_Byte* base, - T1_Int size ) + T1_Long size ) { T1_Parser* parser = &loader->parser; @@ -571,8 +590,8 @@ parser->error = 0; { - T1_Byte* cur = base; - T1_Byte* limit = cur + size; + T1_Byte* cur = base; + T1_Byte* limit = cur + size; for ( ;cur < limit; cur++ ) { @@ -587,7 +606,7 @@ while (cur2 < limit && is_alpha(*cur2)) cur2++; len = cur2-cur; - if (len > 0) + if (len > 0 && len < 20) { /* now, compare the immediate name to the keyword table */ T1_KeyWord* keyword = (T1_KeyWord*)t1_keywords; @@ -617,6 +636,7 @@ return parser->error; cur = parser->cursor; + break; } } keyword++; @@ -631,9 +651,11 @@ static void t1_init_loader( T1_Loader* loader, T1_Face face ) { + MEM_Set( loader, 0, sizeof(*loader) ); loader->num_glyphs = 0; loader->num_chars = 0; - + + /* initialize the tables - simply set their 'init' field to 0 */ loader->encoding_table.init = 0; loader->charstrings.init = 0; loader->glyph_names.init = 0; @@ -685,6 +707,18 @@ /* to the Type1 data */ type1->num_glyphs = loader.num_glyphs; + if ( !loader.subrs.init ) + { + FT_ERROR(( "T1.Open_Face: no subrs array in face !!\n" )); + error = FT_Err_Invalid_File_Format; + } + + if ( !loader.charstrings.init ) + { + FT_ERROR(( "T1.Open_Face: no charstrings array in face !!\n" )); + error = FT_Err_Invalid_File_Format; + } + loader.subrs.init = 0; type1->num_subrs = loader.num_subrs; type1->subrs_block = loader.subrs.block; diff --git a/src/type1z/t1objs.c b/src/type1z/t1objs.c index f00e4caf7..82b4108b2 100644 --- a/src/type1z/t1objs.c +++ b/src/type1z/t1objs.c @@ -20,6 +20,7 @@ #include #include +#include /* Required by tracing mode */ #undef FT_COMPONENT @@ -164,12 +165,25 @@ T1_Face face ) { T1_Error error; + PSNames_Interface* psnames; (void)face_index; (void)face; face->root.num_faces = 1; + psnames = (PSNames_Interface*)face->psnames; + if (!psnames) + { + /* look-up the PSNames driver */ + FT_Driver psnames_driver; + + psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" ); + if (psnames_driver) + face->psnames = (PSNames_Interface*) + (psnames_driver->interface.format_interface); + } + /* open the tokenizer, this will also check the font format */ error = T1_Open_Face( face ); if (error) goto Exit; diff --git a/src/type1z/t1parse.c b/src/type1z/t1parse.c index a326d3cf7..ea862147b 100644 --- a/src/type1z/t1parse.c +++ b/src/type1z/t1parse.c @@ -367,9 +367,18 @@ cur++; /* now, read the coordinates */ - for ( ; cur < limit; cur++ ) + for ( ; cur < limit; ) { - c = *cur; + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) break; + + cur++; + if (cur >= limit) goto Exit; + } + if (count >= max_coords || c == ender) break; @@ -414,9 +423,18 @@ cur++; /* now, read the values */ - for ( ; cur < limit; cur++ ) + for ( ; cur < limit; ) { - c = *cur; + /* skip whitespace in front of data */ + for (;;) + { + c = *cur; + if ( c != ' ' && c != '\t' ) break; + + cur++; + if (cur >= limit) goto Exit; + } + if (count >= max_values || c == ender) break; @@ -442,10 +460,19 @@ T1_String* result; FT_Error error; - /* first of all, skip everything until we encounter a string */ - while ( cur < limit && *cur != '(' ) cur++; - cur++; - if (cur >= limit) return 0; + /* XXX : some stupid fonts have a "Notice" or "Copyright" string */ + /* that simply doesn't begin with an opening parenthesis, even */ + /* though they have a closing one !!! E.g. "amuncial.pfb" */ + /* */ + /* We must deal with these ill-fated cases there. Note that */ + /* these fonts didn't work with the old Type 1 driver as the */ + /* notice/copyright was not recognized as a valid string token */ + /* and made the old token parser commit errors.. */ + + while ( cur < limit && (*cur == ' ' || *cur == '\t')) cur++; + if (cur+1 >= limit) return 0; + + if (*cur == '(') cur++; /* skip the opening parenthesis, if there is one */ *cursor = cur; count = 0; @@ -470,7 +497,7 @@ /* now copy the string */ MEM_Copy( result, *cursor, len ); result[len] = '\0'; - + *cursor = cur; return result; } @@ -632,43 +659,44 @@ else parser->in_pfb = 1; - /* now, try to load the "size" bytes of the "base" dictionary we */ - /* found previously */ - - /* if it's a memory-based resource, set up pointers */ - if ( !stream->read ) - { - parser->base_dict = (T1_Byte*)stream->base + stream->pos; - parser->base_len = size; - parser->in_memory = 1; - - /* check that the "size" field is valid */ - if ( FILE_Skip(size) ) goto Exit; - } - else - { - /* read segment in memory */ - if ( ALLOC( parser->base_dict, size ) || - FILE_Read( parser->base_dict, size ) ) - goto Exit; - } - - /* Now check font format, we must see a '%!PS-AdobeFont-1' */ - /* or a '%!FontType' */ - { - if ( size <= 16 || - ( strncmp( (const char*)parser->base_dict, "%!PS-AdobeFont-1", 16 ) && - strncmp( (const char*)parser->base_dict, "%!FontType", 10 ) ) ) - { - FT_TRACE2(( "Not a Type1 font\n" )); - error = T1_Err_Invalid_File_Format; - } - else - { - parser->cursor = parser->base_dict; - parser->limit = parser->cursor + parser->base_len; - } - } + /* now, try to load the "size" bytes of the "base" dictionary we */ + /* found previously */ + + /* if it's a memory-based resource, set up pointers */ + if ( !stream->read ) + { + parser->base_dict = (T1_Byte*)stream->base + stream->pos; + parser->base_len = size; + parser->in_memory = 1; + + /* check that the "size" field is valid */ + if ( FILE_Skip(size) ) goto Exit; + } + else + { + /* read segment in memory */ + if ( ALLOC( parser->base_dict, size ) || + FILE_Read( parser->base_dict, size ) ) + goto Exit; + parser->base_len = size; + } + + /* Now check font format, we must see a '%!PS-AdobeFont-1' */ + /* or a '%!FontType' */ + { + if ( size <= 16 || + ( strncmp( (const char*)parser->base_dict, "%!PS-AdobeFont-1", 16 ) && + strncmp( (const char*)parser->base_dict, "%!FontType", 10 ) ) ) + { + FT_TRACE2(( "Not a Type1 font\n" )); + error = T1_Err_Invalid_File_Format; + } + else + { + parser->cursor = parser->base_dict; + parser->limit = parser->cursor + parser->base_len; + } + } Exit: if (error && !parser->in_memory) diff --git a/src/type1z/type1z.c b/src/type1z/type1z.c index 5000a8aee..422f200b6 100644 --- a/src/type1z/type1z.c +++ b/src/type1z/type1z.c @@ -34,5 +34,8 @@ #include #include #include -#include + +#ifndef T1_CONFIG_OPTION_NO_AFM +#include +#endif