ref: 95bec28220c8f08d3db92d6048abc4756726fe2c
parent: 861ba624db9df65529a11718d3eabc45b124dbeb
author: David Turner <[email protected]>
date: Tue Feb 15 07:55:57 EST 2000
updated version of the experimental Type 1 driver (this thing now works even better than the "regular" driver, but is much smaller). Provides no hinter !!
--- a/src/type1z/rules.mk
+++ b/src/type1z/rules.mk
@@ -108,7 +108,7 @@
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
@@ -115,9 +115,9 @@
# 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)
--- /dev/null
+++ b/src/type1z/t1afm.c
@@ -1,0 +1,222 @@
+/***************************************************************************
+ *
+ * t1afm.c - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#include <t1afm.h>
+#include <ftstream.h>
+#include <t1types.h>
+#include <stdlib.h> /* 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;
+ }
+
--- /dev/null
+++ b/src/type1z/t1afm.h
@@ -1,0 +1,47 @@
+/***************************************************************************
+ *
+ * t1afm.h - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+#include <ftobjs.h>
+
+/* 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 */
--- 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 */
--- a/src/type1z/t1driver.c
+++ b/src/type1z/t1driver.c
@@ -17,13 +17,16 @@
#include <t1driver.h>
#include <t1gload.h>
+#include <t1afm.h>
#include <ftdebug.h>
#include <ftstream.h>
+#include <psnames.h>
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1driver
+#ifndef T1_CONFIG_OPTION_NO_AFM
/*************************************************************************/
/* */
/* <Function> */
@@ -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;
}
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* 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. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* 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
+
/******************************************************************/
/* */
/* <Function> Set_Char_Sizes */
@@ -130,7 +186,172 @@
return T1_Reset_Size(size);
}
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* 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;
+ }
+
/******************************************************************/
/* */
/* <Struct> FT_DriverInterface */
@@ -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,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getInterface) 0,
+#else
(FTDriver_getInterface) Get_Interface,
+#endif
- (FTDriver_initFace) T1_Init_Face,
+ (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,
};
- /*************************************************************************/
- /* */
- /* <Function> */
- /* getDriverInterface */
- /* */
- /* <Description> */
- /* 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. */
- /* */
- /* <Return> */
- /* 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
+ /******************************************************************/
+ /* */
+ /* <Function> Get_FreeType_Driver_Interface */
+ /* */
+ /* <Description> */
+ /* 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. */
+ /* */
+ /* <Return> */
+ /* 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 */
--- a/src/type1z/t1driver.h
+++ b/src/type1z/t1driver.h
@@ -22,7 +22,7 @@
#include <t1errors.h>
EXPORT_DEF
- const FT_DriverInterface t1_driver_interface;
+ const FT_DriverInterface t1z_driver_interface;
#endif /* T1DRIVER_H */
--- a/src/type1z/t1gload.c
+++ b/src/type1z/t1gload.c
@@ -17,9 +17,75 @@
#include <t1gload.h>
#include <ftdebug.h>
-#include <t1encode.h>
#include <ftstream.h>
+#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,10 +330,10 @@
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,
@@ -274,7 +340,16 @@
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;
- break;
+ 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 4: /* vmoveto */
+ case 255: /* four bytes integer */
{
- USE_ARGS(1);
- y += top[0];
- builder->path_begun = 1;
- goto Clear_Stack;
+ 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;
- case 5: /* rlineto */
+ 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: /*************************************************/
{
- if ( start_point( builder, x, y ) ) goto Memory_Error;
+ 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;
- 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;
+ break;
}
-
- case 6: /* hlineto */
+
+
+ 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: /****************************************************/
{
+ 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 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;
-
- USE_ARGS(1);
+
x += top[0];
goto Add_Line;
}
-
- case 7: /* vlineto */
+
+
+ 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(1);
- y += top[0];
- goto Add_Line;
+ x += top[0];
+ y += top[1];
+ Add_Line:
+ if (add_point1( builder, x, y )) goto Memory_Error;
+ break;
}
-
- case 8: /* rrcurveto */
+
+
+ case op_rmoveto: /*************************************************/
{
+ FT_TRACE4(( " rmoveto" ));
+ x += top[0];
+ y += top[1];
+ break;
+ }
+
+ 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;
-
- 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;
- }
- }
+ decoder->top = top;
+
+ } /* general operator processing */
- 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:
--- a/src/type1z/t1load.c
+++ b/src/type1z/t1load.c
@@ -63,10 +63,8 @@
#include <t1types.h>
#include <t1errors.h>
-#include <t1encode.h>
#include <t1config.h>
#include <t1load.h>
-
#include <stdio.h>
#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,7 +488,7 @@
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' &&
@@ -488,6 +495,12 @@
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;
@@ -684,6 +706,18 @@
/* now, propagate the subrs, charstrings and glyphnames tables */
/* 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;
--- a/src/type1z/t1objs.c
+++ b/src/type1z/t1objs.c
@@ -20,6 +20,7 @@
#include <t1gload.h>
#include <t1load.h>
+#include <psnames.h>
/* Required by tracing mode */
#undef FT_COMPONENT
@@ -164,11 +165,24 @@
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 );
--- 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,11 +460,20 @@
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)
--- a/src/type1z/type1z.c
+++ b/src/type1z/type1z.c
@@ -34,5 +34,8 @@
#include <t1objs.c>
#include <t1driver.c>
#include <t1gload.c>
-#include <t1encode.c>
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include <t1afm.c>
+#endif