ref: 728da1c863acace7dc9dcd0d732ccdb30c6f210d
parent: a1be2dcee38dd4448a365fd8932c52cca52f5445
author: David Turner <[email protected]>
date: Tue Jun 27 19:21:51 EDT 2000
changed file names and some functions names to avoid conflicts with the "type1" driver.
--- a/src/type1z/rules.mk
+++ b/src/type1z/rules.mk
@@ -31,17 +31,17 @@
# Type1 driver sources (i.e., C files)
#
-T1Z_DRV_SRC := $(T1Z_DIR_)t1parse.c \
- $(T1Z_DIR_)t1load.c \
- $(T1Z_DIR_)t1driver.c \
- $(T1Z_DIR_)t1afm.c \
- $(T1Z_DIR_)t1gload.c \
- $(T1Z_DIR_)t1objs.c
+T1Z_DRV_SRC := $(T1Z_DIR_)z1parse.c \
+ $(T1Z_DIR_)z1load.c \
+ $(T1Z_DIR_)z1driver.c \
+ $(T1Z_DIR_)z1afm.c \
+ $(T1Z_DIR_)z1gload.c \
+ $(T1Z_DIR_)z1objs.c
# Type1 driver headers
#
T1Z_DRV_H := $(T1Z_DRV_SRC:%.c=%.h) \
- $(T1Z_DIR_)t1tokens.h
+ $(T1Z_DIR_)z1tokens.h
# Type1z driver object(s)
--- a/src/type1z/t1afm.c
+++ /dev/null
@@ -1,229 +1,0 @@
-/***************************************************************************
- *
- * t1afm.c - support for reading Type 1 AFM files
- *
- *
- ***************************************************************************/
-
-#include <t1afm.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/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[n];
-
- 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;
- int sign = 1;
-
- /* skip everything that is not a number */
- while ( p < limit && (*p < '0' || *p > '9') )
- {
- sign = 1;
- if (*p == '-')
- sign = -1;
-
- p++;
- }
-
- while ( p < limit && (*p >= '0' && *p < '9') )
- {
- sum = sum*10 + (*p - '0');
- p++;
- }
- *start = p;
- return sum*sign;
- }
-
-
-#undef KERN_INDEX
-#define KERN_INDEX(g1,g2) (((FT_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;
-
- FT_ULong index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2);
- FT_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_Face t1_face,
- FT_Stream stream )
- {
- 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;
- FT_ULong index = KERN_INDEX(glyph1,glyph2);
-
- /* simple binary search */
- min = afm->kern_pairs;
- max = min + afm->num_pairs-1;
-
- while (min <= max)
- {
- FT_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;
- }
-
--- a/src/type1z/t1afm.h
+++ /dev/null
@@ -1,50 +1,0 @@
-/***************************************************************************
- *
- * t1afm.h - support for reading Type 1 AFM files
- *
- *
- ***************************************************************************/
-
-#ifndef T1AFM_H
-#define T1AFM_H
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/ftobjs.h>
-#include <freetype/internal/t1types.h>
-#include <freetype/internal/t1errors.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_Face face,
- FT_Stream stream );
-
-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/t1driver.c
+++ /dev/null
@@ -1,300 +1,0 @@
-/*******************************************************************
- *
- * t1driver.c
- *
- * High-level Type1 driver interface for FreeType 2.0
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <t1driver.h>
-#include <t1gload.h>
-#include <t1load.h>
-#include <t1afm.h>
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/psnames.h>
-
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1driver
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Interface */
- /* */
- /* <Description> */
- /* Each driver can provide one or more extensions to the base */
- /* FreeType API. These can be used to access format specific */
- /* features (e.g., all TrueType/OpenType resources share a common */
- /* file structure and common tables which can be accessed through the */
- /* `sfnt' interface), or more simply generic ones (e.g., the */
- /* `postscript names' interface which can be used to retrieve the */
- /* PostScript name of a given glyph index). */
- /* */
- /* <InOut> */
- /* driver :: A handle to a driver object. */
- /* */
- /* <Input> */
- /* interface :: A string designing the interface. Examples are */
- /* `sfnt', `post_names', `charmaps', etc. */
- /* */
- /* <Return> */
- /* A typeless pointer to the extension's interface (normally a table */
- /* of function pointers). Returns NULL if the requested extension */
- /* isn't available (i.e., wasn't compiled in the driver at build */
- /* time). */
- /* */
- static
- FT_Module_Interface Get_Interface( FT_Driver driver,
- const FT_String* interface )
- {
- UNUSED(driver);
- UNUSED(interface);
-
-#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
- if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
- return (FT_Module_Interface)T1_Get_Multi_Master;
-
- if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
- return (FT_Module_Interface)T1_Set_MM_Design;
-
- if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
- return (FT_Module_Interface)T1_Set_MM_Blend;
-#endif
- return 0;
- }
-
-
-#ifndef T1_CONFIG_OPTION_NO_AFM
- /*************************************************************************/
- /* */
- /* <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
- FT_Error Get_Kerning( T1_Face face,
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_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> */
- /* 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
- FT_UInt Get_Char_Index( FT_CharMap charmap,
- FT_Long charcode )
- {
- T1_Face face;
- FT_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,
- (FT_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;
- }
-
-
- const FT_Driver_Class t1z_driver_class =
- {
- {
- ft_module_font_driver | ft_module_driver_scalable,
- sizeof( FT_DriverRec ),
-
- "type1z",
- 0x10000,
- 0x20000,
-
- 0, /* format interface */
-
- (FT_Module_Constructor) T1_Init_Driver,
- (FT_Module_Destructor) T1_Done_Driver,
- (FT_Module_Requester) Get_Interface,
- },
-
- sizeof( T1_FaceRec ),
- sizeof( T1_SizeRec ),
- sizeof( T1_GlyphSlotRec ),
-
- (FTDriver_initFace) T1_Init_Face,
- (FTDriver_doneFace) T1_Done_Face,
- (FTDriver_initSize) 0,
- (FTDriver_doneSize) 0,
- (FTDriver_initGlyphSlot) 0,
- (FTDriver_doneGlyphSlot) 0,
-
- (FTDriver_setCharSizes) 0,
- (FTDriver_setPixelSizes) 0,
- (FTDriver_loadGlyph) T1_Load_Glyph,
- (FTDriver_getCharIndex) Get_Char_Index,
-
-#ifdef T1_CONFIG_OPTION_NO_AFM
- (FTDriver_getKerning) 0,
- (FTDriver_attachFile) 0,
-#else
- (FTDriver_getKerning) Get_Kerning,
- (FTDriver_attachFile) T1_Read_AFM,
-#endif
- (FTDriver_getAdvances) 0
-
- };
-
-
- /******************************************************************/
- /* */
- /* <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(const FT_Driver_Class*) getDriverClass( void )
- {
- return &t1z_driver_class;
- }
-
-#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
-
-
--- a/src/type1z/t1driver.h
+++ /dev/null
@@ -1,26 +1,0 @@
-/*******************************************************************
- *
- * t1driver.h
- *
- * High-level Type1 driver interface for FreeType 2.0
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef T1DRIVER_H
-#define T1DRIVER_H
-
-#include <freetype/internal/ftdriver.h>
-
- FT_EXPORT_VAR(const FT_Driver_Class) t1z_driver_class;
-
-#endif /* T1DRIVER_H */
-
--- a/src/type1z/t1gload.c
+++ /dev/null
@@ -1,1382 +1,0 @@
-/*******************************************************************
- *
- * t1gload.c 1.0
- *
- * Type1 Glyph Loader.
- *
- * Copyright 1996-1999 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <t1gload.h>
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/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 FT_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 */
- };
-
-
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
- /********** *********/
- /********** *********/
- /********** GENERIC CHARSTRINGS PARSING *********/
- /********** *********/
- /********** *********/
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
-
-/*********************************************************************
- *
- * <Function>
- * T1_Init_Builder
- *
- * <Description>
- * Initialise a given glyph builder.
- *
- * <Input>
- * builder :: glyph builder to initialise
- * face :: current face object
- * size :: current size object
- * glyph :: current glyph object
- *
- *********************************************************************/
-
- LOCAL_FUNC
- void T1_Init_Builder( T1_Builder* builder,
- T1_Face face,
- T1_Size size,
- T1_GlyphSlot glyph )
- {
- builder->path_begun = 0;
- builder->load_points = 1;
-
- builder->face = face;
- builder->glyph = glyph;
- builder->memory = face->root.memory;
-
- if (glyph)
- {
- FT_GlyphLoader* loader = glyph->root.loader;
-
- builder->loader = loader;
- builder->current = &loader->current.outline;
- builder->base = &loader->base.outline;
-
- FT_GlyphLoader_Rewind(loader);
- }
-
- if (size)
- {
- builder->scale_x = size->root.metrics.x_scale;
- builder->scale_y = size->root.metrics.y_scale;
- }
-
- builder->pos_x = 0;
- builder->pos_y = 0;
-
- builder->left_bearing.x = 0;
- builder->left_bearing.y = 0;
- builder->advance.x = 0;
- builder->advance.y = 0;
- }
-
-
-/*********************************************************************
- *
- * <Function>
- * T1_Done_Builder
- *
- * <Description>
- * Finalise a given glyph builder. Its content can still be
- * used after the call, but the function saves important information
- * within the corresponding glyph slot.
- *
- * <Input>
- * builder :: glyph builder to initialise
- *
- *********************************************************************/
-
- LOCAL_FUNC
- void T1_Done_Builder( T1_Builder* builder )
- {
- T1_GlyphSlot glyph = builder->glyph;
-
- if (glyph)
- glyph->root.outline = *builder->base;
- }
-
-
-
-/*********************************************************************
- *
- * <Function>
- * T1_Init_Decoder
- *
- * <Description>
- * Initialise a given Type 1 decoder for parsing
- *
- * <Input>
- * decoder :: Type 1 decoder to initialise
- * funcs :: hinter functions interface
- *
- *********************************************************************/
-
- LOCAL_FUNC
- void T1_Init_Decoder( T1_Decoder* decoder )
- {
- decoder->top = 0;
- decoder->zone = 0;
- decoder->flex_state = 0;
- decoder->num_flex_vectors = 0;
- decoder->blend = 0;
-
- /* Clear loader */
- MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
- }
-
-
- /* check that there is enough room for "count" more points */
- static
- FT_Error check_points( T1_Builder* builder,
- FT_Int count )
- {
- return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
- }
-
-
- /* add a new point, do not check room */
- static
- void add_point( T1_Builder* builder,
- FT_Pos x,
- FT_Pos y,
- FT_Byte flag )
- {
- FT_Outline* outline = builder->current;
-
- if (builder->load_points)
- {
- FT_Vector* point = outline->points + outline->n_points;
- FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
-
- point->x = x;
- point->y = y;
- *control = ( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
-
- builder->last = *point;
- }
-
- outline->n_points++;
- }
-
-
- /* check room for a new on-curve point, then add it */
- static
- FT_Error add_point1( T1_Builder* builder,
- FT_Pos x,
- FT_Pos y )
- {
- FT_Error error;
-
- error = check_points(builder,1);
- if (!error)
- add_point( builder, x, y, 1 );
-
- return error;
- }
-
-
- /* check room for a new contour, then add it */
- static
- FT_Error add_contour( T1_Builder* builder )
- {
- FT_Outline* outline = builder->current;
- FT_Error error;
-
- if (!builder->load_points)
- {
- outline->n_contours++;
- return FT_Err_Ok;
- }
-
- /* realloc contours array if necessary */
- error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
- if (!error)
- {
- if (outline->n_contours > 0)
- outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
-
- outline->n_contours++;
- }
- return error;
- }
-
- /* if a path was begun, add its first on-curve point */
- static
- FT_Error start_point( T1_Builder* builder,
- FT_Pos x,
- FT_Pos y )
- {
- /* test wether we're building a new contour */
- if (!builder->path_begun)
- {
- FT_Error error;
-
- builder->path_begun = 1;
- error = add_contour( builder );
- if (error) return error;
- }
- return add_point1( builder, x, y );
- }
-
-
- /* close the current contour */
- static
- void close_contour( T1_Builder* builder )
- {
- FT_Outline* outline = builder->current;
-
- if ( outline->n_contours > 0 )
- outline->contours[outline->n_contours-1] = outline->n_points-1;
- }
-
-
-/*********************************************************************
- *
- * <Function>
- * lookup_glyph_by_stdcharcode
- *
- * <Description>
- * Lookup a given glyph by its StandardEncoding charcode. Used
- * to implement the SEAC Type 1 operator.
- *
- * <Input>
- * face :: current face object
- * charcode :: charcode to look for
- *
- * <Return>
- * glyph index in font face. Returns -1 if the corresponding
- * glyph wasn't found.
- *
- *********************************************************************/
-
- static
- FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
- FT_Int charcode )
- {
- FT_Int n;
- const FT_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 = psnames->adobe_std_strings(
- psnames->adobe_std_encoding[charcode]);
-
- for ( n = 0; n < face->type1.num_glyphs; n++ )
- {
- FT_String* name = (FT_String*)face->type1.glyph_names[n];
-
- if ( name && strcmp(name,glyph_name) == 0 )
- return n;
- }
-
- return -1;
- }
-
-
-
-/*********************************************************************
- *
- * <Function>
- * t1operator_seac
- *
- * <Description>
- * Implements the "seac" Type 1 operator for a Type 1 decoder
- *
- * <Input>
- * decoder :: current Type 1 decoder
- * asb :: accent's side bearing
- * adx :: horizontal position of accent
- * ady :: vertical position of accent
- * bchar :: base character's StandardEncoding charcode
- * achar :: accent character's StandardEncoding charcode
- *
- * <Return>
- * Error code. 0 means success.
- *
- *********************************************************************/
-
- static
- FT_Error t1operator_seac( T1_Decoder* decoder,
- FT_Pos asb,
- FT_Pos adx,
- FT_Pos ady,
- FT_Int bchar,
- FT_Int achar )
- {
- FT_Error error;
- FT_Int bchar_index, achar_index, n_base_points;
- FT_Outline* cur = decoder->builder.current;
- FT_Outline* base = decoder->builder.base;
- FT_Vector left_bearing, advance;
- T1_Face face = decoder->builder.face;
- T1_Font* type1 = &face->type1;
-
- bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
- achar_index = lookup_glyph_by_stdcharcode( face, achar );
-
- if ( bchar_index < 0 || achar_index < 0 )
- {
- FT_ERROR(( "t1operator_seac: invalid seac character code arguments\n" ));
- return T1_Err_Syntax_Error;
- }
-
- /* if we are trying to load a composite glyph, do not load the */
- /* accent character and return the array of subglyphs. */
- if ( decoder->builder.no_recurse )
- {
-
- FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
- FT_GlyphLoader* loader = glyph->loader;
- FT_SubGlyph* subg;
-
- /* reallocate subglyph array if necessary */
- error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
- if (error) goto Exit;
-
- subg = loader->current.subglyphs;
-
- /* subglyph 0 = base character */
- subg->index = bchar_index;
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
- FT_SUBGLYPH_FLAG_USE_MY_METRICS;
- subg->arg1 = 0;
- subg->arg2 = 0;
- subg++;
-
- /* subglyph 1 = accent character */
- subg->index = achar_index;
- subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
- subg->arg1 = adx - asb;
- subg->arg2 = ady;
-
- /* set up remaining glyph fields */
- glyph->num_subglyphs = 2;
- glyph->format = ft_glyph_format_composite;
-
- loader->current.num_subglyphs = 2;
- }
-
- /* First load `bchar' in builder */
- /* now load the unscaled outline */
-
- FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
-
- error = T1_Parse_CharStrings( decoder,
- type1->charstrings [bchar_index],
- type1->charstrings_len[bchar_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
- if ( error ) goto Exit;
-
- n_base_points = cur->n_points;
-
- {
- /* save the left bearing and width of the base character */
- /* as they will be erased by the next load. */
-
- left_bearing = decoder->builder.left_bearing;
- advance = decoder->builder.advance;
-
- decoder->builder.left_bearing.x = 0;
- decoder->builder.left_bearing.y = 0;
-
- /* Now load `achar' on top of */
- /* the base outline */
- error = T1_Parse_CharStrings( decoder,
- type1->charstrings [achar_index],
- type1->charstrings_len[achar_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
- if ( error ) return error;
-
- /* restore the left side bearing and */
- /* advance width of the base character */
-
- decoder->builder.left_bearing = left_bearing;
- decoder->builder.advance = advance;
-
- /* Finally, move the accent */
- if ( decoder->builder.load_points )
- {
- FT_Outline dummy;
-
- dummy.n_points = base->n_points - n_base_points;
- dummy.points = base->points + n_base_points;
- FT_Outline_Translate( &dummy, adx - asb, ady );
- }
- }
- Exit:
- return error;
- }
-
-
-/*********************************************************************
- *
- * <Function>
- * T1_Parse_CharStrings
- *
- * <Description>
- * Parses a given Type 1 charstrings program
- *
- * <Input>
- * decoder :: current Type 1 decoder
- * charstring_base :: base of the charstring stream
- * charstring_len :: length in bytes of the charstring stream
- * num_subrs :: number of sub-routines
- * subrs_base :: array of sub-routines addresses
- * subrs_len :: array of sub-routines lengths
- *
- * <Return>
- * Error code. 0 means success.
- *
- *********************************************************************/
-
-#define USE_ARGS(n) top -= n; if (top < decoder->stack) goto Stack_Underflow
-
- LOCAL_FUNC
- FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_Int charstring_len,
- FT_Int num_subrs,
- FT_Byte** subrs_base,
- FT_Int* subrs_len )
- {
- FT_Error error;
- T1_Decoder_Zone* zone;
- FT_Byte* ip;
- FT_Byte* limit;
- T1_Builder* builder = &decoder->builder;
- FT_Outline* outline;
- FT_Pos x, y;
-
- /* First of all, initialise the decoder */
- decoder->top = decoder->stack;
- decoder->zone = decoder->zones;
- zone = decoder->zones;
-
- builder->path_begun = 0;
-
- zone->base = charstring_base;
- limit = zone->limit = charstring_base + charstring_len;
- ip = zone->cursor = zone->base;
-
- error = T1_Err_Ok;
- outline = builder->current;
-
- x = builder->pos_x;
- y = builder->pos_y;
-
- /* now, execute loop */
- while ( ip < limit )
- {
- FT_Int* top = decoder->top;
- T1_Operator op = op_none;
- FT_Long value = 0;
-
- /********************************************************************/
- /* */
- /* Decode operator or operand */
- /* */
- /* */
-
- /* First of all, decompress operator or value */
- switch (*ip++)
- {
- 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:
- {
- 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 ------------------------ */
- {
- FT_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,
- (FT_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;;
- }
-
- case 12:
- case 13:
- {
- /* counter control hints, clear stack */
- top = decoder->stack;
- break;
- }
-
- case 14:
- case 15:
- case 16:
- case 17:
- case 18: /* multiple masters */
- {
- T1_Blend* blend = decoder->blend;
- FT_UInt num_points, nn, mm;
- FT_Int* delta;
- FT_Int* values;
-
- if (!blend)
- {
- FT_ERROR(( "T1.Parse_CharStrings: unexpected multiple masters operator !!\n" ));
- goto Syntax_Error;
- }
-
- num_points = top[1] - 13 + (top[1] == 18);
- if (top[0] != num_points*blend->num_designs)
- {
- FT_ERROR(( "T1.Parse_CharStrings: incorrect number of mm arguments\n" ));
- goto Syntax_Error;
- }
-
- top -= blend->num_designs*num_points;
- if (top < decoder->stack)
- goto Stack_Underflow;
-
- /* we want to compute: */
- /* */
- /* a0*w0 + a1*w1 + ... + ak*wk */
- /* */
- /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
- /* however, given that w0 + w1 + ... + wk == 1, we can */
- /* rewrite it easily as: */
- /* */
- /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
- /* */
- /* where k == num_designs-1 */
- /* */
- /* I guess that's why it's written in this "compact" */
- /* form.. */
- /* */
- /* */
- delta = top + num_points;
- values = top;
- for ( nn = 0; nn < num_points; nn++ )
- {
- FT_Int x = values[0];
- for ( mm = 1; mm < blend->num_designs; mm++ )
- x += FT_MulFix( *delta++, blend->weight_vector[mm] );
-
- *values++ = x;
- }
- /* note that "top" will be incremented later by calls to "pop" */
- 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 */
- {
- FT_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 */
- FT_GlyphLoader_Add( builder->loader );
-
- /* 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 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;
-
- 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;
-
- x += top[0];
- y += top[1];
- Add_Line:
- if (add_point1( builder, x, y )) goto Memory_Error;
- break;
- }
-
-
- 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;
-
- x += top[0];
- y += top[1];
- add_point( builder, x, y, 0 );
-
- x += top[2];
- y += top[3];
- add_point( builder, x, y, 0 );
-
- x += top[4];
- y += top[5];
- add_point( builder, x, y, 1 );
- break;
- }
-
-
- case op_vhcurveto: /**********************************************/
- {
- 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;
- }
-
-
- 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];
- ++top;
- }
- else
- {
- FT_ERROR(( "T1.Parse_CharStrings : division by 0\n" ));
- goto Syntax_Error;
- }
- break;
- }
-
-
- case op_callsubr: /***********************************************/
- {
- FT_Int index;
-
- FT_TRACE4(( " callsubr" ));
- index = top[0];
- if ( index < 0 || index >= num_subrs )
- {
- FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
- goto Syntax_Error;
- }
-
- if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
- {
- FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
- goto Syntax_Error;
- }
-
- zone->cursor = ip; /* save current instruction pointer */
-
- zone++;
- zone->base = subrs_base[index];
- zone->limit = zone->base + subrs_len[index];
- zone->cursor = zone->base;
-
- if (!zone->base)
- {
- FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
- goto Syntax_Error;
- }
-
- decoder->zone = zone;
- ip = zone->base;
- limit = zone->limit;
- break;
- }
-
-
- case op_pop: /****************************************************/
- {
- FT_TRACE4(( " pop" ));
- /* theorically, the arguments are already on the stack */
- top++;
- break;
- }
-
-
- case op_return: /************************************************/
- {
- FT_TRACE4(( " return" ));
- if ( zone <= decoder->zones )
- {
- FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
- goto Syntax_Error;
- }
-
- zone--;
- ip = zone->cursor;
- limit = zone->limit;
- decoder->zone = zone;
- break;
- }
-
- case op_dotsection: /*********************************************/
- {
- FT_TRACE4(( " dotsection" ));
- break;
- }
-
- case op_hstem: /**************************************************/
- {
- FT_TRACE4(( " hstem" ));
- break;
- }
-
- case op_hstem3: /*************************************************/
- {
- FT_TRACE4(( " hstem3" ));
- break;
- }
-
- case op_vstem: /**************************************************/
- {
- FT_TRACE4(( " vstem" ));
- break;
- }
-
- case op_vstem3: /*************************************************/
- {
- FT_TRACE4(( " vstem3" ));
- break;
- }
-
- case op_setcurrentpoint: /*****************************************/
- {
- FT_TRACE4(( " setcurrentpoint" ));
- FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
- goto Syntax_Error;
- }
-
- default:
- FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
- goto Syntax_Error;
- }
-
- decoder->top = top;
-
- } /* general operator processing */
-
-
- } /* while ip < limit */
- FT_TRACE4(( "..end..\n\n" ));
- return error;
-
- Syntax_Error:
- return T1_Err_Syntax_Error;
-
- Stack_Underflow:
- return T1_Err_Stack_Underflow;
-
- Memory_Error:
- return builder->error;
- }
-
-
-
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
- /********** *********/
- /********** *********/
- /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
- /********** *********/
- /********** The following code is in charge of computing *********/
- /********** the maximum advance width of the font. It *********/
- /********** quickly process each glyph charstring to *********/
- /********** extract the value from either a "sbw" or "seac" *********/
- /********** operator. *********/
- /********** *********/
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Compute_Max_Advance( T1_Face face,
- FT_Int *max_advance )
- {
- FT_Error error;
- T1_Decoder decoder;
- FT_Int glyph_index;
- T1_Font* type1 = &face->type1;
-
- *max_advance = 0;
-
- /* Initialise load decoder */
- T1_Init_Decoder( &decoder );
- T1_Init_Builder( &decoder.builder, face, 0, 0 );
-
- decoder.blend = face->blend;
- decoder.builder.metrics_only = 1;
- decoder.builder.load_points = 0;
-
- /* For each glyph, parse the glyph charstring and extract */
- /* the advance width.. */
- for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
- {
- /* now get load the unscaled outline */
- error = T1_Parse_CharStrings( &decoder,
- type1->charstrings [glyph_index],
- type1->charstrings_len[glyph_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
- /* ignore the error if one occured - skip to next glyph */
- }
-
- *max_advance = decoder.builder.advance.x;
- return T1_Err_Ok;
- }
-
-
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
- /********** *********/
- /********** *********/
- /********** UNHINTED GLYPH LOADER *********/
- /********** *********/
- /********** The following code is in charge of loading a *********/
- /********** single outline. It completely ignores hinting *********/
- /********** and is used when FT_LOAD_NO_HINTING is set. *********/
- /********** *********/
- /**********************************************************************/
- /**********************************************************************/
- /**********************************************************************/
-
-
- LOCAL_FUNC
- FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
- T1_Size size,
- FT_Int glyph_index,
- FT_Int load_flags )
- {
- FT_Error error;
- T1_Decoder decoder;
- T1_Face face = (T1_Face)glyph->root.face;
- FT_Bool hinting;
- T1_Font* type1 = &face->type1;
-
- if (load_flags & FT_LOAD_NO_RECURSE)
- load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-
- glyph->x_scale = size->root.metrics.x_scale;
- glyph->y_scale = size->root.metrics.y_scale;
-
- glyph->root.outline.n_points = 0;
- glyph->root.outline.n_contours = 0;
-
- hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
- ( load_flags & FT_LOAD_NO_HINTING ) == 0;
-
- glyph->root.format = ft_glyph_format_none;
-
- {
- T1_Init_Decoder( &decoder );
- T1_Init_Builder( &decoder.builder, face, size, glyph );
-
- decoder.blend = ((T1_Face)glyph->root.face)->blend;
- decoder.builder.no_recurse = (FT_Bool)!!(load_flags & FT_LOAD_NO_RECURSE);
-
- /* now load the unscaled outline */
- error = T1_Parse_CharStrings( &decoder,
- type1->charstrings [glyph_index],
- type1->charstrings_len[glyph_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
-
- /* save new glyph tables */
- T1_Done_Builder( &decoder.builder );
- }
-
- /* Now, set the metrics.. - this is rather simple, as : */
- /* the left side bearing is the xMin, and the top side */
- /* bearing the yMax.. */
- if (!error)
- {
- /* for composite glyphs, return only the left side bearing and the */
- /* advance width.. */
- if ( load_flags & FT_LOAD_NO_RECURSE )
- {
- glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
- glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
- }
- else
- {
- FT_BBox cbox;
- FT_Glyph_Metrics* metrics = &glyph->root.metrics;
-
- /* copy the _unscaled_ advance width */
- metrics->horiAdvance = decoder.builder.advance.x;
-
- /* make up vertical metrics */
- metrics->vertBearingX = 0;
- metrics->vertBearingY = 0;
- metrics->vertAdvance = 0;
-
- glyph->root.format = ft_glyph_format_outline;
-
- glyph->root.outline.flags &= ft_outline_owner;
- if ( size && size->root.metrics.y_ppem < 24 )
- glyph->root.outline.flags |= ft_outline_high_precision;
-
- glyph->root.outline.flags |= ft_outline_reverse_fill;
-
- /*
- glyph->root.outline.second_pass = TRUE;
- glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
- glyph->root.outline.dropout_mode = 2;
- */
-
- if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
- {
- /* scale the outline and the metrics */
- FT_Int n;
- FT_Outline* cur = decoder.builder.base;
- FT_Vector* vec = cur->points;
- FT_Fixed x_scale = glyph->x_scale;
- FT_Fixed y_scale = glyph->y_scale;
-
- /* First of all, scale the points */
- for ( n = cur->n_points; n > 0; n--, vec++ )
- {
- vec->x = FT_MulFix( vec->x, x_scale );
- vec->y = FT_MulFix( vec->y, y_scale );
- }
-
- FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
- /* Then scale the metrics */
- metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
-
- metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
- metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
- metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
- }
-
- /* apply the font matrix */
- FT_Outline_Transform( &glyph->root.outline, &face->type1.font_matrix );
-
- /* compute the other metrics */
- FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
- /* grid fit the bounding box if necessary */
- if (hinting)
- {
- cbox.xMin &= -64;
- cbox.yMin &= -64;
- cbox.xMax = ( cbox.xMax+63 ) & -64;
- cbox.yMax = ( cbox.yMax+63 ) & -64;
- }
-
- metrics->width = cbox.xMax - cbox.xMin;
- metrics->height = cbox.yMax - cbox.yMin;
-
- metrics->horiBearingX = cbox.xMin;
- metrics->horiBearingY = cbox.yMax;
- }
- }
- return error;
- }
-
--- a/src/type1z/t1gload.h
+++ /dev/null
@@ -1,188 +1,0 @@
-/*******************************************************************
- *
- * t1gload.h 1.0
- *
- * Type1 Glyph Loader.
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- *
- * The Type 1 glyph loader uses three distinct objects to build
- * scaled and hinted outlines from a charstrings program. These are :
- *
- * - a glyph builder, T1_Builder, used to store the built outline
- *
- * - a glyph hinter, T1_Hinter, used to record and apply the stem
- * hints
- *
- * - a charstrings interpreter, T1_Decoder, used to parse the
- * Type 1 charstrings stream, manage a stack and call the builder
- * and/or hinter depending on the opcodes.
- *
- * Ideally, a Type 2 glyph loader would only need to have its own
- * T2_Decoder object (assuming the hinter is able to manage all
- * kinds of hints).
- *
- ******************************************************************/
-
-#ifndef T1GLOAD_H
-#define T1GLOAD_H
-
-#include <t1objs.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
-/*************************************************************************/
-/* */
-/* <Structure> T1_Builder */
-/* */
-/* <Description> */
-/* a structure used during glyph loading to store its outline. */
-/* */
-/* <Fields> */
-/* system :: current system object */
-/* face :: current face object */
-/* glyph :: current glyph slot */
-/* */
-/* current :: current glyph outline */
-/* base :: base glyph outline */
-/* */
-/* max_points :: maximum points in builder outline */
-/* max_contours :: maximum contours in builder outline */
-/* */
-/* last :: last point position */
-/* */
-/* scale_x :: horizontal scale ( FUnits to sub-pixels ) */
-/* scale_y :: vertical scale ( FUnits to sub-pixels ) */
-/* pos_x :: horizontal translation (composite glyphs) */
-/* pos_y :: vertical translation (composite glyph) */
-/* */
-/* left_bearing :: left side bearing point */
-/* advance :: horizontal advance vector */
-/* */
-/* path_begun :: flag, indicates that a new path has begun */
-/* load_points :: flag, if not set, no points are loaded */
-/* */
-/* error :: an error code that is only used to report */
-/* memory allocation problems.. */
-/* */
-/* metrics_only :: a boolean indicating that we only want to */
-/* compute the metrics of a given glyph, not load */
-/* all of its points.. */
-/* */
-
- typedef struct T1_Builder_
- {
- FT_Memory memory;
- T1_Face face;
- T1_GlyphSlot glyph;
- FT_GlyphLoader* loader;
-
- FT_Outline* current; /* the current glyph outline */
- FT_Outline* base; /* the composite glyph outline */
-
- FT_Vector last;
-
- FT_Fixed scale_x;
- FT_Fixed scale_y;
-
- FT_Pos pos_x;
- FT_Pos pos_y;
-
- FT_Vector left_bearing;
- FT_Vector advance;
-
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
- FT_Bool no_recurse;
-
- FT_Error error; /* only used for memory errors */
- FT_Bool metrics_only;
-
- } T1_Builder;
-
-
- /* execution context charstring zone */
- typedef struct T1_Decoder_Zone_
- {
- FT_Byte* base;
- FT_Byte* limit;
- FT_Byte* cursor;
-
- } T1_Decoder_Zone;
-
-
- typedef struct T1_Decoder_
- {
- T1_Builder builder;
-
- FT_Int stack[ T1_MAX_CHARSTRINGS_OPERANDS ];
- FT_Int* top;
-
- T1_Decoder_Zone zones[ T1_MAX_SUBRS_CALLS+1 ];
- T1_Decoder_Zone* zone;
-
- FT_Int flex_state;
- FT_Int num_flex_vectors;
- FT_Vector flex_vectors[7];
-
- T1_Blend* blend; /* for multiple masters */
-
- } T1_Decoder;
-
-
-
- LOCAL_DEF
- void T1_Init_Builder( T1_Builder* builder,
- T1_Face face,
- T1_Size size,
- T1_GlyphSlot glyph );
-
- LOCAL_DEF
- void T1_Done_Builder( T1_Builder* builder );
-
-
- LOCAL_DEF
- void T1_Init_Decoder( T1_Decoder* decoder );
-
-
- /* Compute the maximum advance width of a font through quick parsing */
- LOCAL_DEF
- FT_Error T1_Compute_Max_Advance( T1_Face face,
- FT_Int *max_advance );
-
-
- /* This function is exported, because it is used by the T1Dump utility */
- LOCAL_DEF
- FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_Int charstring_len,
- FT_Int num_subrs,
- FT_Byte** subrs_base,
- FT_Int* subrs_len );
-
-
-
- LOCAL_DEF
- FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
- T1_Size size,
- FT_Int glyph_index,
- FT_Int load_flags );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* T1GLOAD_H */
--- a/src/type1z/t1load.c
+++ /dev/null
@@ -1,1473 +1,0 @@
-/*******************************************************************
- *
- * t1load.h 2.0
- *
- * Type1 Loader.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- *
- * This is the new and improved Type 1 data loader for FreeType 2.
- * The old loader has several problems: it is slow, complex, difficult
- * to maintain, and contains incredible hacks to make it accept some
- * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5%
- * of the Type 1 fonts on my machine still aren't loaded correctly
- * by it.
- *
- * This version is much simpler, much faster and also easier to
- * read and maintain by a great order of magnitude. The idea behind
- * it is to _not_ try to read the Type 1 token stream with a state
- * machine (i.e. a Postscript-like interpreter) but rather to perform
- * simple pattern-matching.
- *
- * Indeed, nearly all data definitions follow a simple pattern
- * like :
- *
- * ..... /Field <data> ....
- *
- * where <data> can be a number, a boolean, a string, or an
- * array of numbers. There are a few exceptions, namely the
- * encoding, font name, charstrings and subrs and they are
- * handled with a special pattern-matching routine.
- *
- * All other common cases are handled very simply. The matching
- * rules are defined in the file "t1tokens.h" through the use
- * of several macros calls PARSE_XXXX
- *
- * This file is included twice here, the first time to generate
- * parsing callback functions, the second to generate a table
- * of keywords (with pointers to the associated callback).
- *
- * The function "parse_dict" simply scans *linearly* a given
- * dictionary (either the top-level or private one) and calls
- * the appropriate callback when it encounters an immediate
- * keyword.
- *
- * This is by far the fastest way one can find to parse and read
- * all data :-)
- *
- * This led to tremendous code size reduction. Note that later,
- * the glyph loader will also be _greatly_ simplified, and the
- * automatic hinter will replace the clumsy "t1hinter"..
- *
- ******************************************************************/
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/config/ftconfig.h>
-#include <freetype/ftmm.h>
-
-#include <freetype/internal/t1types.h>
-#include <freetype/internal/t1errors.h>
-#include <t1load.h>
-#include <stdio.h>
-
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1load
-
-#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
- /***************************************************************************/
- /***************************************************************************/
- /***** *****/
- /***** MULTIPLE MASTERS SUPPORT *****/
- /***** *****/
- /***************************************************************************/
- /***************************************************************************/
-
- static FT_Error t1_allocate_blend( T1_Face face,
- FT_UInt num_designs,
- FT_UInt num_axis )
- {
- T1_Blend* blend;
- FT_Memory memory = face->root.memory;
- FT_Error error = 0;
-
- blend = face->blend;
- if (!blend)
- {
- if ( ALLOC( blend, sizeof(*blend) ) )
- goto Exit;
-
- face->blend = blend;
- }
-
- /* allocate design data if needed */
- if (num_designs > 0)
- {
- if (blend->num_designs == 0)
- {
- /* allocate the blend "private" and "font_info" dictionaries */
- if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
- ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
- ALLOC_ARRAY( blend->weight_vector, num_designs*2, FT_Fixed ) )
- goto Exit;
-
- blend->default_weight_vector = blend->weight_vector + num_designs;
-
- blend->font_infos[0] = &face->type1.font_info;
- blend->privates [0] = &face->type1.private_dict;
- blend->num_designs = num_designs;
- }
- else if (blend->num_designs != num_designs)
- goto Fail;
- }
-
- /* allocate axis data if needed */
- if (num_axis > 0)
- {
- if (blend->num_axis != 0 && blend->num_axis != num_axis)
- goto Fail;
-
- blend->num_axis = num_axis;
- }
-
- /* allocate the blend design pos table if needed */
- num_designs = blend->num_designs;
- num_axis = blend->num_axis;
- if ( num_designs && num_axis && blend->design_pos[0] == 0)
- {
- FT_UInt n;
-
- if ( ALLOC_ARRAY( blend->design_pos[0], num_designs*num_axis, FT_Fixed ) )
- goto Exit;
-
- for ( n = 1; n < num_designs; n++ )
- blend->design_pos[n] = blend->design_pos[0] + num_axis*n;
- }
-
- Exit:
- return error;
- Fail:
- error = -1;
- goto Exit;
- }
-
- LOCAL_FUNC FT_Error T1_Get_Multi_Master( T1_Face face,
- FT_Multi_Master* master )
- {
- T1_Blend* blend = face->blend;
- FT_UInt n;
- FT_Error error;
-
- error = T1_Err_Invalid_Argument;
- if (blend)
- {
- master->num_axis = blend->num_axis;
- master->num_designs = blend->num_designs;
- for ( n = 0; n < blend->num_axis; n++ )
- {
- FT_MM_Axis* axis = master->axis + n;
- T1_DesignMap* map = blend->design_map + n;
-
- axis->name = blend->axis_names[n];
- axis->minimum = map->design_points[0];
- axis->maximum = map->design_points[map->num_points-1];
- }
- error = 0;
- }
- return error;
- }
-
-
- LOCAL_FUNC FT_Error T1_Set_MM_Blend( T1_Face face,
- FT_UInt num_coords,
- FT_Fixed* coords )
- {
- T1_Blend* blend = face->blend;
- FT_Error error;
- FT_UInt n, m;
-
- error = T1_Err_Invalid_Argument;
- if (blend && blend->num_axis == num_coords)
- {
- /* recompute the weight vector from the blend coordinates */
- error = 0;
- for ( n = 0; n < blend->num_designs; n++ )
- {
- FT_Fixed result = 0x10000L; /* 1.0 fixed */
- for ( m = 0; m < blend->num_axis; m++ )
- {
- FT_Fixed factor;
-
- /* get current blend axis position */
- factor = coords[m];
- if (factor < 0) factor = 0;
- if (factor > 0x10000L) factor = 0x10000L;
-
- if ((n & (1 << m)) == 0)
- factor = 0x10000L - factor;
-
- result = FT_MulFix( result, factor );
- }
- blend->weight_vector[n] = result;
- }
- error = 0;
- }
- return error;
- }
-
-
- LOCAL_FUNC FT_Error T1_Set_MM_Design( T1_Face face,
- FT_UInt num_coords,
- FT_Long* coords )
- {
- T1_Blend* blend = face->blend;
- FT_Error error;
- FT_UInt n, p;
-
- error = T1_Err_Invalid_Argument;
- if (blend && blend->num_axis == num_coords)
- {
- /* compute the blend coordinates through the blend design map */
- FT_Fixed final_blends[ T1_MAX_MM_DESIGNS ];
-
- for ( n = 0; n < blend->num_axis; n++ )
- {
- FT_Long design = coords[n];
- FT_Fixed the_blend;
- T1_DesignMap* map = blend->design_map + n;
- FT_Fixed* designs = map->design_points;
- FT_Fixed* blends = map->blend_points;
- FT_Int before = -1, after = -1;
-
- for ( p = 0; p < map->num_points; p++ )
- {
- FT_Fixed p_design = designs[p];
-
- /* exact match ? */
- if (design == p_design)
- {
- the_blend = blends[p];
- goto Found;
- }
-
- if (design < p_design)
- {
- after = p;
- break;
- }
-
- before = p;
- }
-
- /* now, interpolate if needed */
- if (before < 0)
- the_blend = blends[0];
-
- else if (after < 0)
- the_blend = blends[map->num_points-1];
-
- else
- the_blend = FT_MulDiv( design - designs[before],
- blends [after] - blends [before],
- designs[after] - designs[before] );
- Found:
- final_blends[n] = the_blend;
- }
-
- error = T1_Set_MM_Blend( face, num_coords, final_blends );
- }
- return error;
- }
-
-
- LOCAL_FUNC void T1_Done_Blend( T1_Face face )
- {
- FT_Memory memory = face->root.memory;
- T1_Blend* blend = face->blend;
-
- if (blend)
- {
- FT_UInt num_designs = blend->num_designs;
- FT_UInt num_axis = blend->num_axis;
- FT_UInt n;
-
- /* release design pos table */
- FREE( blend->design_pos[0] );
- for ( n = 1; n < num_designs; n++ )
- blend->design_pos[n] = 0;
-
- /* release blend "private" and "font info" dictionaries */
- FREE( blend->privates[1] );
- FREE( blend->font_infos[1] );
- for ( n = 0; n < num_designs; n++ )
- {
- blend->privates [n] = 0;
- blend->font_infos[n] = 0;
- }
-
- /* release weight vectors */
- FREE( blend->weight_vector );
- blend->default_weight_vector = 0;
-
- /* release axis names */
- for ( n = 0; n < num_axis; n++ )
- FREE( blend->axis_names[n] );
-
- /* release design map */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_DesignMap* dmap = blend->design_map + n;
- FREE( dmap->design_points );
- dmap->num_points = 0;
- }
-
- FREE( face->blend );
- }
- }
-
-
-
- static void parse_blend_axis_types( T1_Face face, T1_Loader* loader )
- {
- T1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
- FT_Int n, num_axis;
- FT_Error error = 0;
- T1_Blend* blend;
- FT_Memory memory;
-
- /* take an array of objects */
- T1_ToTokenArray( &loader->parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
- if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
- {
- FT_ERROR(( "T1.parse_blend_axis_types: incorrect number of axis: %d\n",
- num_axis ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* allocate blend if necessary */
- error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
- if (error) goto Exit;
-
- blend = face->blend;
- memory = face->root.memory;
-
- /* each token is an immediate containing the name of the axis */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_Token_Rec* token = axis_tokens + n;
- FT_Byte* name;
- FT_Int len;
-
- /* skip first slash, if any */
- if (token->start[0] == '/')
- token->start++;
-
- len = token->limit - token->start;
- if (len <= 0)
- {
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- if ( ALLOC( blend->axis_names[n], len+1 ) )
- goto Exit;
-
- name = (FT_Byte*)blend->axis_names[n];
- MEM_Copy( name, token->start, len );
- name[len] = 0;
- }
-
- Exit:
- loader->parser.error = error;
- }
-
-
- static void parse_blend_design_positions( T1_Face face, T1_Loader* loader )
- {
- T1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ];
- FT_Int num_designs;
- FT_Int num_axis;
- T1_Parser* parser = &loader->parser;
-
- FT_Error error = 0;
- T1_Blend* blend;
-
- /* get the array of design tokens - compute number of designs */
- T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
- if (num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS)
- {
- FT_ERROR(( "T1.design positions: incorrect number of designs: %d\n",
- num_designs ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- {
- FT_Byte* old_cursor = parser->cursor;
- FT_Byte* old_limit = parser->limit;
- FT_UInt n;
-
- blend = face->blend;
- num_axis = 0; /* make compiler happy */
- for ( n = 0; n < (FT_UInt)num_designs; n++ )
- {
- T1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ];
- T1_Token_Rec* token;
- FT_Int axis, n_axis;
-
- /* read axis/coordinates tokens */
- token = design_tokens + n;
- parser->cursor = token->start - 1;
- parser->limit = token->limit + 1;
- T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
-
- if (n == 0)
- {
- num_axis = n_axis;
- error = t1_allocate_blend( face, num_designs, num_axis );
- if (error) goto Exit;
- blend = face->blend;
- }
- else if (n_axis != num_axis)
- {
- FT_ERROR(( "T1.design_positions: incorrect table\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* now, read each axis token into the design position */
- for (axis = 0; axis < n_axis; axis++ )
- {
- T1_Token_Rec* token2 = axis_tokens + axis;
- parser->cursor = token2->start;
- parser->limit = token2->limit;
- blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
- }
- }
-
- loader->parser.cursor = old_cursor;
- loader->parser.limit = old_limit;
- }
-
- Exit:
- loader->parser.error = error;
- }
-
- static void parse_blend_design_map( T1_Face face, T1_Loader* loader )
- {
- FT_Error error = 0;
- T1_Parser* parser = &loader->parser;
- T1_Blend* blend;
- T1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
- FT_Int n, num_axis;
- FT_Byte* old_cursor;
- FT_Byte* old_limit;
- FT_Memory memory = face->root.memory;
-
- T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
- if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
- {
- FT_ERROR(( "T1.design map: incorrect number of axis: %d\n",
- num_axis ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
- old_cursor = parser->cursor;
- old_limit = parser->limit;
-
- error = t1_allocate_blend( face, 0, num_axis );
- if (error) goto Exit;
- blend = face->blend;
-
- /* now, read each axis design map */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_DesignMap* map = blend->design_map + n;
- T1_Token_Rec* token;
- FT_Int p, num_points;
-
- token = axis_tokens + n;
- parser->cursor = token->start;
- parser->limit = token->limit;
-
- /* count the number of map points */
- {
- FT_Byte* p = token->start;
- FT_Byte* limit = token->limit;
-
- num_points = 0;
- for ( ; p < limit; p++ )
- if (p[0] == '[')
- num_points++;
- }
- if (num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS)
- {
- FT_ERROR(( "T1.design map: incorrect table\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* allocate design map data */
- if ( ALLOC_ARRAY( map->design_points, num_points*2, FT_Fixed ) )
- goto Exit;
- map->blend_points = map->design_points + num_points;
- map->num_points = (FT_Byte)num_points;
-
- for ( p = 0; p < num_points; p++ )
- {
- map->design_points[p] = T1_ToInt( parser );
- map->blend_points [p] = T1_ToFixed( parser, 0 );
- }
- }
-
- parser->cursor = old_cursor;
- parser->limit = old_limit;
- Exit:
- parser->error = error;
- }
-
- static void parse_weight_vector( T1_Face face, T1_Loader* loader )
- {
- FT_Error error = 0;
- T1_Parser* parser = &loader->parser;
- T1_Blend* blend = face->blend;
- T1_Token_Rec master;
- FT_UInt n;
- FT_Byte* old_cursor;
- FT_Byte* old_limit;
-
- if (!blend || blend->num_designs == 0)
- {
- FT_ERROR(( "t1.weight_vector: too early !!\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- T1_ToToken( parser, &master );
- if (master.type != t1_token_array)
- {
- FT_ERROR(( "t1.weight_vector: incorrect format !!\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- old_cursor = parser->cursor;
- old_limit = parser->limit;
-
- parser->cursor = master.start;
- parser->limit = master.limit;
- for ( n = 0; n < blend->num_designs; n++ )
- {
- blend->default_weight_vector[n] =
- blend->weight_vector[n] = T1_ToFixed( parser, 0 );
- }
-
- parser->cursor = old_cursor;
- parser->limit = old_limit;
- Exit:
- parser->error = error;
- }
-
- /* the keyword /shareddict appears in some multiple master fonts with a lot */
- /* of Postscript garbage behind it (that's completely out of spec !!), we */
- /* detect it and terminate the parsing */
- static void parse_shared_dict( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
-
- UNUSED(face);
-
- parser->cursor = parser->limit;
- parser->error = 0;
- }
-#endif
-
- /***************************************************************************/
- /***************************************************************************/
- /***** *****/
- /***** TYPE 1 SYMBOL PARSING *****/
- /***** *****/
- /***************************************************************************/
- /***************************************************************************/
-
- /*********************************************************************
- *
- * First of all, define the token field static variables. This is
- * a set of T1_Field_Rec variables used later..
- *
- *********************************************************************/
-
-#define T1_NEW_STRING( _name, _field ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_STRING( T1TYPE, _field );
-
-#define T1_NEW_BOOL( _name, _field ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_BOOL( T1TYPE, _field );
-
-#define T1_NEW_NUM( _name, _field ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM( T1TYPE, _field );
-
-#define T1_NEW_FIXED( _name, _field ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED( T1TYPE, _field, _power );
-
-#define T1_NEW_NUM_TABLE( _name, _field, _max, _count ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
-
-#define T1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
-
-#define T1_NEW_NUM_TABLE2( _name, _field, _max ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
-
-#define T1_NEW_FIXED_TABLE2( _name, _field, _max ) \
- static const T1_Field_Rec t1_field_ ## _field = T1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
-
-
-#define T1_FONTINFO_STRING(n,f) T1_NEW_STRING(n,f)
-#define T1_FONTINFO_NUM(n,f) T1_NEW_NUM(n,f)
-#define T1_FONTINFO_BOOL(n,f) T1_NEW_BOOL(n,f)
-#define T1_PRIVATE_NUM(n,f) T1_NEW_NUM(n,f)
-#define T1_PRIVATE_FIXED(n,f) T1_NEW_FIXED(n,f)
-#define T1_PRIVATE_NUM_TABLE(n,f,m,c) T1_NEW_NUM_TABLE(n,f,m,c)
-#define T1_PRIVATE_NUM_TABLE2(n,f,m) T1_NEW_NUM_TABLE2(n,f,m)
-#define T1_TOPDICT_NUM(n,f) T1_NEW_NUM(n,f)
-#define T1_TOPDICT_NUM_FIXED2(n,f,m) T1_NEW_FIXED_TABLE2(n,f,m)
-
-/* including this file defines all field variables */
-#include <t1tokens.h>
-
- /*********************************************************************
- *
- * Second, define the keyword variables. This is a set of T1_KeyWord
- * structures used to model the way each keyword is "loaded"..
- *
- *********************************************************************/
-
- typedef void (*T1_Parse_Func)( T1_Face face, T1_Loader* loader );
-
- typedef enum T1_KeyWord_Type_
- {
- t1_keyword_callback = 0,
- t1_keyword_field,
- t1_keyword_field_table
-
- } T1_KeyWord_Type;
-
- typedef enum T1_KeyWord_Location_
- {
- t1_keyword_type1 = 0,
- t1_keyword_font_info,
- t1_keyword_private
-
- } T1_KeyWord_Location;
-
- typedef struct T1_KeyWord_
- {
- const char* name;
- T1_KeyWord_Type type;
- T1_KeyWord_Location location;
- T1_Parse_Func parsing;
- const T1_Field_Rec* field;
-
- } T1_KeyWord;
-
-
-#define T1_KEYWORD_CALLBACK( name, callback ) \
- { name, t1_keyword_callback, t1_keyword_type1, callback, 0 }
-
-#define T1_KEYWORD_TYPE1( name, f ) \
- { name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f }
-
-#define T1_KEYWORD_FONTINFO( name, f ) \
- { name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f }
-
-#define T1_KEYWORD_PRIVATE( name, f ) \
- { name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f }
-
-#define T1_KEYWORD_FONTINFO_TABLE( name, f ) \
- { name, t1_keyword_field_table, t1_keyword_font_info, 0, &t1_field_ ## f }
-
-#define T1_KEYWORD_PRIVATE_TABLE( name, f ) \
- { name, t1_keyword_field_table, t1_keyword_private, 0, &t1_field_ ## f }
-
-#undef T1_FONTINFO_STRING
-#undef T1_FONTINFO_NUM
-#undef T1_FONTINFO_BOOL
-#undef T1_PRIVATE_NUM
-#undef T1_PRIVATE_FIXED
-#undef T1_PRIVATE_NUM_TABLE
-#undef T1_PRIVATE_NUM_TABLE2
-#undef T1_TOPDICT_NUM
-#undef T1_TOPDICT_NUM_FIXED2
-
-#define T1_FONTINFO_STRING(n,f) T1_KEYWORD_FONTINFO(n,f),
-#define T1_FONTINFO_NUM(n,f) T1_KEYWORD_FONTINFO(n,f),
-#define T1_FONTINFO_BOOL(n,f) T1_KEYWORD_FONTINFO(n,f),
-#define T1_PRIVATE_NUM(n,f) T1_KEYWORD_PRIVATE(n,f),
-#define T1_PRIVATE_FIXED(n,f) T1_KEYWORD_PRIVATE(n,f),
-#define T1_PRIVATE_NUM_TABLE(n,f,m,c) T1_KEYWORD_PRIVATE_TABLE(n,f),
-#define T1_PRIVATE_NUM_TABLE2(n,f,m) T1_KEYWORD_PRIVATE_TABLE(n,f),
-#define T1_TOPDICT_NUM(n,f) T1_KEYWORD_TYPE1(n,f),
-#define T1_TOPDICT_NUM_FIXED2(n,f,m) T1_KEYWORD_TYPE1(n,f),
-
-
- static FT_Error t1_load_keyword( T1_Face face,
- T1_Loader* loader,
- T1_KeyWord* keyword )
- {
- FT_Error error;
- void* dummy_object;
- void** objects;
- FT_UInt max_objects;
- T1_Blend* blend = face->blend;
-
- /* if the keyword has a dedicated callback, call it */
- if (keyword->type == t1_keyword_callback)
- {
- keyword->parsing( face, loader );
- error = loader->parser.error;
- goto Exit;
- }
-
- /* now, the keyword is either a simple field, or a table of fields */
- /* we are now going to take care of it.. */
- switch (keyword->location)
- {
- case t1_keyword_font_info:
- {
- dummy_object = &face->type1.font_info;
- objects = &dummy_object;
- max_objects = 0;
- if (blend)
- {
- objects = (void**)blend->font_infos;
- max_objects = blend->num_designs;
- }
- }
- break;
-
- case t1_keyword_private:
- {
- dummy_object = &face->type1.private_dict;
- objects = &dummy_object;
- max_objects = 0;
- if (blend)
- {
- objects = (void**)blend->privates;
- max_objects = blend->num_designs;
- }
- }
- break;
-
- default:
- dummy_object = &face->type1;
- objects = &dummy_object;
- max_objects = 0;
- }
-
- if (keyword->type == t1_keyword_field_table)
- error = T1_Load_Field_Table( &loader->parser, keyword->field, objects, max_objects, 0 );
- else
- error = T1_Load_Field( &loader->parser, keyword->field, objects, max_objects, 0 );
-
- Exit:
- return error;
- }
-
-
- static
- int is_space( char c )
- {
- return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
- }
-
- static
- int is_alpha( char c )
- {
- return ( (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- (c == '.') ||
- (c == '_') );
- }
-
- static
- void skip_whitespace( T1_Parser* parser )
- {
- FT_Byte* cur = parser->cursor;
-
- while ( cur < parser->limit && is_space(*cur) )
- cur++;
-
- parser->cursor = cur;
- }
-
- static
- void skip_blackspace( T1_Parser* parser )
- {
- FT_Byte* cur = parser->cursor;
-
- while ( cur < parser->limit && !is_space(*cur) )
- cur++;
-
- parser->cursor = cur;
- }
-
- static
- int read_binary_data( T1_Parser* parser, FT_Int *size, FT_Byte* *base )
- {
- FT_Byte* cur;
- FT_Byte* limit = parser->limit;
-
- /* the binary data has the following format */
- /* */
- /* "size" [white*] RD white ....... ND */
- /* */
-
- skip_whitespace(parser);
- cur = parser->cursor;
-
- if ( cur < limit && (FT_Byte)(*cur-'0') < 10 )
- {
- *size = T1_ToInt(parser);
-
- skip_whitespace(parser);
- skip_blackspace(parser); /* "RD" or "-|" or something else */
-
- /* there is only one whitespace char after the */
- /* "RD" or "-|" token */
- *base = parser->cursor + 1;
-
- parser->cursor += *size+1;
- return 1;
- }
-
- FT_ERROR(( "type1.read_binary_data: invalid size field\n" ));
- parser->error = T1_Err_Invalid_File_Format;
- return 0;
- }
-
-
- /* we will now define the routines used to handle */
- /* the /Encoding, /Subrs and /CharStrings */
- /* dictionaries.. */
-
- static
- void parse_font_name( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- FT_Error error;
- FT_Memory memory = parser->memory;
- FT_Int len;
- FT_Byte* cur;
- FT_Byte* cur2;
- FT_Byte* limit;
-
- skip_whitespace(parser);
- cur = parser->cursor;
- limit = parser->limit;
- if ( cur >= limit-1 || *cur != '/' ) return;
-
- cur++;
- cur2 = cur;
- while (cur2 < limit && is_alpha(*cur2)) cur2++;
- len = cur2-cur;
- if (len > 0)
- {
- if ( ALLOC( face->type1.font_name, len+1 ) )
- {
- parser->error = error;
- return;
- }
-
- MEM_Copy( face->type1.font_name, cur, len );
- face->type1.font_name[len] = '\0';
- }
- parser->cursor = cur2;
- }
-
- static
- void parse_font_bbox( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- FT_Short temp[4];
- FT_BBox* bbox = &face->type1.font_bbox;
-
- (void)T1_ToCoordArray( parser, 4, temp );
- bbox->xMin = temp[0];
- bbox->yMin = temp[1];
- bbox->xMax = temp[2];
- bbox->yMax = temp[3];
- }
-
- static
- void parse_font_matrix( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- FT_Matrix* matrix = &face->type1.font_matrix;
- FT_Fixed temp[4];
-
- (void)T1_ToFixedArray( parser, 4, temp, 3 );
- matrix->xx = temp[0];
- matrix->yx = temp[1];
- matrix->xy = temp[2];
- matrix->yy = temp[3];
- }
-
-
-
- static
- void parse_encoding( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- FT_Byte* cur = parser->cursor;
- FT_Byte* limit = parser->limit;
-
- /* skip whitespace */
- while (is_space(*cur))
- {
- cur++;
- if (cur >= limit)
- {
- FT_ERROR(( "type1.parse_encoding: out of bounds !!\n" ));
- parser->error = T1_Err_Invalid_File_Format;
- return;
- }
- }
-
- /* if we have a number, then the encoding is an array, */
- /* and we must load it now */
- if ((FT_Byte)(*cur - '0') < 10)
- {
- T1_Encoding* encode = &face->type1.encoding;
- FT_Int count, n;
- T1_Table* char_table = &loader->encoding_table;
- FT_Memory memory = parser->memory;
- FT_Error error;
-
- /* read the number of entries in the encoding, should be 256 */
- count = T1_ToInt( parser );
- if (parser->error) return;
-
- /* we use a T1_Table to store our charnames */
- encode->num_chars = count;
- if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ||
- ALLOC_ARRAY( encode->char_name, count, FT_String* ) ||
- (error = T1_New_Table( char_table, count, memory )) != 0 )
- {
- parser->error = error;
- return;
- }
-
- /* now, we will need to read a record of the form */
- /* ... charcode /charname ... for each entry in our table */
- /* */
- /* we simply look for a number followed by an immediate */
- /* name. Note that this ignores correctly the sequence */
- /* that is often seen in type1 fonts : */
- /* */
- /* 0 1 255 { 1 index exch /.notdef put } for dup */
- /* */
- /* used to clean the encoding array before anything else */
- /* */
- /* we stop when we encounter a "def" */
- /* */
-
- cur = parser->cursor;
- limit = parser->limit;
- n = 0;
-
- for ( ; cur < limit; )
- {
- FT_Byte c;
-
- c = *cur;
-
- /* we stop when we encounter a 'def' */
- if ( c == 'd' && cur+3 < limit )
- {
- if ( cur[1] == 'e' &&
- cur[2] == 'f' &&
- is_space(cur[-1]) &&
- is_space(cur[3]) )
- {
- FT_TRACE6(( "encoding end\n" ));
- break;
- }
- }
-
- /* otherwise, we must find a number before anything else */
- if ( (FT_Byte)(c-'0') < 10 )
- {
- FT_Int charcode;
-
- parser->cursor = cur;
- charcode = T1_ToInt(parser);
- cur = parser->cursor;
-
- /* skip whitespace */
- while (cur < limit && is_space(*cur)) cur++;
-
- if (cur < limit && *cur == '/')
- {
- /* bingo, we have an immediate name - it must be a */
- /* character name */
- FT_Byte* cur2 = cur+1;
- FT_Int len;
-
- while (cur2 < limit && is_alpha(*cur2)) cur2++;
- len = cur2-cur-1;
- parser->error = T1_Add_Table( char_table, charcode, cur+1, len+1 );
- char_table->elements[charcode][len] = '\0';
- if (parser->error) return;
-
- cur = cur2;
- }
- }
- else
- cur++;
- }
-
- face->type1.encoding_type = t1_encoding_array;
- parser->cursor = cur;
- }
- /* Otherwise, we should have either "StandardEncoding" or */
- /* "ExpertEncoding" */
- else
- {
- if ( cur+17 < limit &&
- strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
- face->type1.encoding_type = t1_encoding_standard;
-
- else if ( cur+15 < limit &&
- strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
- face->type1.encoding_type = t1_encoding_expert;
-
- else
- {
- FT_ERROR(( "type1.parse_encoding: invalid token !!\n" ));
- parser->error = T1_Err_Invalid_File_Format;
- }
- }
- }
-
-
- static
- void parse_subrs( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- T1_Table* table = &loader->subrs;
- FT_Memory memory = parser->memory;
- FT_Error error;
- FT_Int n;
-
- loader->num_subrs = T1_ToInt( parser );
- if (parser->error) return;
-
- /* initialise subrs array */
- error = T1_New_Table( table, loader->num_subrs, memory );
- if (error) goto Fail;
-
- /* the format is simple : */
- /* */
- /* "index" + binary data */
- /* */
-
- for ( n = 0; n < loader->num_subrs; n++ )
- {
- FT_Int index, size;
- FT_Byte* base;
-
- index = T1_ToInt(parser);
- if (!read_binary_data(parser,&size,&base)) return;
-
- /* some fonts use a value of -1 for lenIV to indicate that */
- /* the charstrings are unencoded.. */
- /* */
- /* thanks to Tom Kacvinsky for pointing this out.. */
- /* */
- if (face->type1.private_dict.lenIV >= 0)
- {
- T1_Decrypt( base, size, 4330 );
- size -= face->type1.private_dict.lenIV;
- base += face->type1.private_dict.lenIV;
- }
-
- error = T1_Add_Table( table, index, base, size );
- if (error) goto Fail;
- }
- return;
-
- Fail:
- parser->error = error;
- }
-
-
-
-
- static
- void parse_charstrings( T1_Face face, T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
- T1_Table* code_table = &loader->charstrings;
- T1_Table* name_table = &loader->glyph_names;
- FT_Memory memory = parser->memory;
- FT_Error error;
-
- FT_Byte* cur;
- FT_Byte* limit = parser->limit;
- FT_Int n;
-
- loader->num_glyphs = T1_ToInt( parser );
- if (parser->error) return;
-
- /* initialise tables */
- error = T1_New_Table( code_table, loader->num_glyphs, memory ) ||
- T1_New_Table( name_table, loader->num_glyphs, memory );
- if (error) goto Fail;
-
- n = 0;
- for ( ;; )
- {
- FT_Int size;
- FT_Byte* base;
-
- /* the format is simple : */
- /* "/glyphname" + binary data */
- /* */
- /* note that we stop when we find a "def" */
- /* */
- skip_whitespace(parser);
- cur = parser->cursor;
- if (cur >= limit) break;
-
- /* 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
- {
- FT_Byte* cur2 = cur+1;
- FT_Int len;
-
- 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;
-
- /* add a trailing zero to the name table */
- name_table->elements[n][len] = '\0';
-
- parser->cursor = cur2;
- if (!read_binary_data(parser,&size,&base)) return;
-
- /* some fonts use a value of -1 for lenIV to indicate that */
- /* the charstrings are unencoded.. */
- /* */
- /* thanks to Tom Kacvinsky for pointing this out.. */
- /* */
- if (face->type1.private_dict.lenIV >= 0)
- {
- T1_Decrypt( base, size, 4330 );
- size -= face->type1.private_dict.lenIV;
- base += face->type1.private_dict.lenIV;
- }
-
- error = T1_Add_Table( code_table, n, base, size );
- if (error) goto Fail;
-
- n++;
- if (n >= loader->num_glyphs)
- break;
- }
- }
- loader->num_glyphs = n;
- return;
-
- Fail:
- parser->error = error;
- }
-
-
-
-
- static
- const T1_KeyWord t1_keywords[] =
- {
-#include <t1tokens.h>
-
- /* now add the special functions... */
- T1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
- T1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
- T1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
- T1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
- T1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
- T1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
-#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
- T1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
- T1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
- T1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
- T1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
- T1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
-#endif
- T1_KEYWORD_CALLBACK( 0, 0 )
- };
-
-
- static
- FT_Error parse_dict( T1_Face face,
- T1_Loader* loader,
- FT_Byte* base,
- FT_Long size )
- {
- T1_Parser* parser = &loader->parser;
-
- parser->cursor = base;
- parser->limit = base + size;
- parser->error = 0;
-
- {
- FT_Byte* cur = base;
- FT_Byte* limit = cur + size;
-
- for ( ;cur < limit; cur++ )
- {
- /* look for "FontDirectory", which causes problems on some fonts */
- if ( *cur == 'F' && cur+25 < limit &&
- strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
- {
- FT_Byte* cur2;
-
- /* skip the "FontDirectory" keyword */
- cur += 13;
- cur2 = cur;
-
- /* lookup the 'known' keyword */
- while (cur < limit && *cur != 'k' && strncmp( (char*)cur, "known", 5 ) )
- cur++;
-
- if (cur < limit)
- {
- T1_Token_Rec token;
-
- /* skip the "known" keyword and the token following it */
- cur += 5;
- loader->parser.cursor = cur;
- T1_ToToken( &loader->parser, &token );
-
- /* if the last token was an array, skip it !! */
- if (token.type == t1_token_array)
- cur2 = parser->cursor;
- }
- cur = cur2;
- }
- /* look for immediates */
- else if (*cur == '/' && cur+2 < limit)
- {
- FT_Byte* cur2;
- FT_Int len;
-
- cur ++;
- cur2 = cur;
- while (cur2 < limit && is_alpha(*cur2)) cur2++;
- len = cur2-cur;
-
- if (len > 0 && len < 22)
- {
- if (!loader->fontdata)
- {
- if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
- loader->fontdata = 1;
- }
- else
- {
- /* now, compare the immediate name to the keyword table */
- T1_KeyWord* keyword = (T1_KeyWord*)t1_keywords;
-
- for (;;)
- {
- FT_Byte* name;
-
- name = (FT_Byte*)keyword->name;
- if (!name) break;
-
- if ( cur[0] == name[0] &&
- len == (FT_Int)strlen((const char*)name) )
- {
- FT_Int n;
- for ( n = 1; n < len; n++ )
- if (cur[n] != name[n])
- break;
-
- if (n >= len)
- {
- /* we found it - run the parsing callback !! */
- parser->cursor = cur2;
- skip_whitespace( parser );
- parser->error = t1_load_keyword( face, loader, keyword );
- if (parser->error)
- return parser->error;
-
- cur = parser->cursor;
- break;
- }
- }
- keyword++;
- }
- }
- }
- }
- }
- }
- return parser->error;
- }
-
- static
- void t1_init_loader( T1_Loader* loader, T1_Face face )
- {
- UNUSED(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;
- loader->subrs.init = 0;
- loader->fontdata = 0;
- }
-
- static
- void t1_done_loader( T1_Loader* loader )
- {
- T1_Parser* parser = &loader->parser;
-
- /* finalize tables */
- T1_Release_Table( &loader->encoding_table );
- T1_Release_Table( &loader->charstrings );
- T1_Release_Table( &loader->glyph_names );
- T1_Release_Table( &loader->subrs );
-
- /* finalize parser */
- T1_Done_Parser( parser );
- }
-
- LOCAL_FUNC
- FT_Error T1_Open_Face( T1_Face face )
- {
- T1_Loader loader;
- T1_Parser* parser;
- T1_Font* type1 = &face->type1;
- FT_Error error;
-
- t1_init_loader( &loader, face );
-
- /* default lenIV */
- type1->private_dict.lenIV = 4;
-
- parser = &loader.parser;
- error = T1_New_Parser( parser, face->root.stream, face->root.memory );
- if (error) goto Exit;
-
- error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
- if (error) goto Exit;
-
- error = T1_Get_Private_Dict( parser );
- if (error) goto Exit;
-
- error = parse_dict( face, &loader, parser->private_dict, parser->private_len );
- if (error) goto Exit;
-
- /* 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 = T1_Err_Invalid_File_Format;
- }
-
- if ( !loader.charstrings.init )
- {
- FT_ERROR(( "T1.Open_Face: no charstrings array in face !!\n" ));
- error = T1_Err_Invalid_File_Format;
- }
-
- loader.subrs.init = 0;
- type1->num_subrs = loader.num_subrs;
- type1->subrs_block = loader.subrs.block;
- type1->subrs = loader.subrs.elements;
- type1->subrs_len = loader.subrs.lengths;
-
- loader.charstrings.init = 0;
- type1->charstrings_block = loader.charstrings.block;
- type1->charstrings = loader.charstrings.elements;
- type1->charstrings_len = loader.charstrings.lengths;
-
- /* we copy the glyph names "block" and "elements" fields */
- /* but the "lengths" field must be released later.. */
- type1->glyph_names_block = loader.glyph_names.block;
- type1->glyph_names = (FT_String**)loader.glyph_names.elements;
- loader.glyph_names.block = 0;
- loader.glyph_names.elements = 0;
-
- /* we must now build type1.encoding when we have a custom */
- /* array.. */
- if ( type1->encoding_type == t1_encoding_array )
- {
- FT_Int charcode, index, min_char, max_char;
- FT_Byte* char_name;
- FT_Byte* glyph_name;
-
- /* OK, we do the following : for each element in the encoding */
- /* table, lookup the index of the glyph having the same name */
- /* the index is then stored in type1.encoding.char_index, and */
- /* a the name to type1.encoding.char_name */
-
- min_char = +32000;
- max_char = -32000;
-
- charcode = 0;
- for ( ; charcode < loader.encoding_table.num_elems; charcode++ )
- {
- type1->encoding.char_index[charcode] = 0;
- type1->encoding.char_name [charcode] = ".notdef";
-
- char_name = loader.encoding_table.elements[charcode];
- if (char_name)
- for ( index = 0; index < type1->num_glyphs; index++ )
- {
- glyph_name = (FT_Byte*)type1->glyph_names[index];
- if ( strcmp( (const char*)char_name,
- (const char*)glyph_name ) == 0 )
- {
- type1->encoding.char_index[charcode] = index;
- type1->encoding.char_name [charcode] = (char*)glyph_name;
-
- if (charcode < min_char) min_char = charcode;
- if (charcode > max_char) max_char = charcode;
- break;
- }
- }
- }
- type1->encoding.code_first = min_char;
- type1->encoding.code_last = max_char;
- type1->encoding.num_chars = loader.num_chars;
- }
-
- Exit:
- t1_done_loader( &loader );
- return error;
- }
--- a/src/type1z/t1load.h
+++ /dev/null
@@ -1,77 +1,0 @@
-/*******************************************************************
- *
- * t1load.h 2.0
- *
- * Type1 Loader.
- *
- * Copyright 1996-2000 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef T1LOAD_H
-#define T1LOAD_H
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1types.h>
-#include <freetype/ftmm.h>
-#include <t1parse.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- typedef struct T1_Loader_
- {
- T1_Parser parser; /* parser used to read the stream */
-
- FT_Int num_chars; /* number of characters in encoding */
- T1_Table encoding_table; /* T1_Table used to store the */
- /* encoding character names */
-
- FT_Int num_glyphs;
- T1_Table glyph_names;
- T1_Table charstrings;
-
- FT_Int num_subrs;
- T1_Table subrs;
- FT_Bool fontdata;
-
- } T1_Loader;
-
- LOCAL_DEF
- FT_Error T1_Open_Face( T1_Face face );
-
-#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
- LOCAL_DEF
- FT_Error T1_Get_Multi_Master( T1_Face face,
- FT_Multi_Master* master );
-
- LOCAL_DEF
- FT_Error T1_Set_MM_Blend( T1_Face face,
- FT_UInt num_coords,
- FT_Fixed* coords );
-
- LOCAL_DEF
- FT_Error T1_Set_MM_Design( T1_Face face,
- FT_UInt num_coords,
- FT_Long* coords );
-
- LOCAL_DEF
- void T1_Done_Blend( T1_Face face );
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* T1LOAD_H */
-
-
-/* END */
--- a/src/type1z/t1objs.c
+++ /dev/null
@@ -1,361 +1,0 @@
-/*******************************************************************
- *
- * t1objs.c 1.0
- *
- * Type1 Objects manager.
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-
-#include <t1gload.h>
-#include <t1load.h>
-#include <freetype/internal/psnames.h>
-#include <t1afm.h>
-
-/* Required by tracing mode */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1objs
-
-/*******************************************************************
- * *
- * FACE FUNCTIONS *
- * *
- * *
- *******************************************************************/
-
-/*******************************************************************
- *
- * <Function> T1_Done_Face
- *
- * <Description>
- * The face object destructor.
- *
- * <Input>
- * face :: typeless pointer to the face object to destroy
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- void T1_Done_Face( T1_Face face )
- {
- FT_Memory memory;
- T1_Font* type1 = &face->type1;
-
- if (face)
- {
- memory = face->root.memory;
-
-#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
- /* release multiple masters information */
- T1_Done_Blend( face );
- face->blend = 0;
-#endif
-
- /* release font info strings */
- {
- T1_FontInfo* info = &type1->font_info;
-
- FREE( info->version );
- FREE( info->notice );
- FREE( info->full_name );
- FREE( info->family_name );
- FREE( info->weight );
- }
-
- /* release top dictionary */
- FREE( type1->charstrings_len );
- FREE( type1->charstrings );
- FREE( type1->glyph_names );
-
- FREE( type1->subrs );
- FREE( type1->subrs_len );
-
- FREE( type1->subrs_block );
- FREE( type1->charstrings_block );
- FREE( type1->glyph_names_block );
-
- FREE( type1->encoding.char_index );
- FREE( type1->font_name );
-
-#ifndef T1_CONFIG_OPTION_NO_AFM
- /* release afm data if present */
- if ( face->afm_data)
- T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
-#endif
-
- /* release unicode map, if any */
- FREE( face->unicode_map.maps );
- face->unicode_map.num_maps = 0;
-
- face->root.family_name = 0;
- face->root.style_name = 0;
- }
- }
-
-/*******************************************************************
- *
- * <Function> T1_Init_Face
- *
- * <Description>
- * The face object constructor.
- *
- * <Input>
- * face :: face record to build
- * Input :: input stream where to load font data
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Init_Face( FT_Stream stream,
- T1_Face face,
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params )
- {
- FT_Error error;
- PSNames_Interface* psnames;
-
- UNUSED(num_params);
- UNUSED(params);
- UNUSED(face_index);
- UNUSED(stream);
-
- face->root.num_faces = 1;
-
- psnames = (PSNames_Interface*)face->psnames;
- if (!psnames)
- {
- psnames = (PSNames_Interface*)
- FT_Get_Module_Interface( FT_FACE_LIBRARY(face), "psnames" );
-
- face->psnames = psnames;
- }
-
- /* open the tokenizer, this will also check the font format */
- error = T1_Open_Face( face );
- if (error) goto Exit;
-
- /* if we just wanted to check the format, leave successfully now */
- if (face_index < 0)
- goto Exit;
-
- /* check the face index */
- if ( face_index != 0 )
- {
- FT_ERROR(( "T1.Init_Face : invalid face index\n" ));
- error = T1_Err_Invalid_Argument;
- goto Exit;
- }
-
- /* Now, load the font program into the face object */
- {
- /* Init the face object fields */
- /* Now set up root face fields */
- {
- FT_Face root = (FT_Face)&face->root;
-
- root->num_glyphs = face->type1.num_glyphs;
- root->num_charmaps = 1;
-
- root->face_index = face_index;
- root->face_flags = FT_FACE_FLAG_SCALABLE;
-
- root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
-
- if ( face->type1.font_info.is_fixed_pitch )
- root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
-
- if ( face->blend )
- root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
-
- /* XXX : TO DO - add kerning with .afm support */
-
- /* get style name - be careful, some broken fonts only */
- /* have a /FontName dictionary entry .. !! */
- root->family_name = face->type1.font_info.family_name;
- if (root->family_name)
- {
- char* full = face->type1.font_info.full_name;
- char* family = root->family_name;
-
- while ( *family && *full == *family )
- {
- family++;
- full++;
- }
-
- root->style_name = ( *full == ' ' ? full+1 : "Regular" );
- }
- else
- {
- /* do we have a /FontName ?? */
- if (face->type1.font_name)
- {
- root->family_name = face->type1.font_name;
- root->style_name = "Regular";
- }
- }
-
- /* no embedded bitmap support */
- root->num_fixed_sizes = 0;
- root->available_sizes = 0;
-
- root->bbox = face->type1.font_bbox;
- root->units_per_EM = 1000;
- root->ascender = (FT_Short)face->type1.font_bbox.yMax;
- root->descender = -(FT_Short)face->type1.font_bbox.yMin;
- root->height = ((root->ascender + root->descender)*12)/10;
-
- /* now compute the maximum advance width */
-
- root->max_advance_width = face->type1.private_dict.standard_width[0];
-
- /* compute max advance width for proportional fonts */
- if (!face->type1.font_info.is_fixed_pitch)
- {
- FT_Int max_advance;
-
- error = T1_Compute_Max_Advance( face, &max_advance );
-
- /* in case of error, keep the standard width */
- if (!error)
- root->max_advance_width = max_advance;
- else
- error = 0; /* clear error */
- }
-
- root->max_advance_height = root->height;
-
- root->underline_position = face->type1.font_info.underline_position;
- root->underline_thickness = face->type1.font_info.underline_thickness;
-
- root->max_points = 0;
- root->max_contours = 0;
- }
- }
-
- /* charmap support - synthetize unicode charmap when possible */
- {
- FT_Face root = &face->root;
- FT_CharMap charmap = face->charmaprecs;
-
- /* synthesize 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];
- }
- Exit:
- return error;
- }
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_Driver
- *
- * <Description>
- * Initialise a given Type 1 driver object
- *
- * <Input>
- * driver :: handle to target driver object
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Init_Driver( T1_Driver driver )
- {
- UNUSED(driver);
- return T1_Err_Ok;
- }
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Driver
- *
- * <Description>
- * finalise a given Type 1 driver
- *
- * <Input>
- * driver :: handle to target Type 1 driver
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Driver( T1_Driver driver )
- {
- UNUSED(driver);
- }
-
-
-/* END */
--- a/src/type1z/t1objs.h
+++ /dev/null
@@ -1,215 +1,0 @@
-/*******************************************************************
- *
- * t1objs.h 1.0
- *
- * Type1 objects definition.
- *
- * Copyright 1996-1999 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- ******************************************************************/
-
-#ifndef T1OBJS_H
-#define T1OBJS_H
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/config/ftconfig.h>
-#include <freetype/internal/t1errors.h>
-#include <freetype/internal/t1types.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- /* The following structures must be defined by the hinter */
- typedef struct T1_Size_Hints_ T1_Size_Hints;
- typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
-
- /***********************************************************************/
- /* */
- /* <Type> T1_Driver */
- /* */
- /* <Description> */
- /* A handle to a Type 1 driver object. */
- /* */
- typedef struct T1_DriverRec_ *T1_Driver;
-
-
- /***********************************************************************/
- /* */
- /* <Type> T1_Size */
- /* */
- /* <Description> */
- /* A handle to a Type 1 size object. */
- /* */
- typedef struct T1_SizeRec_* T1_Size;
-
-
- /***********************************************************************/
- /* */
- /* <Type> T1_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a Type 1 glyph slot object. */
- /* */
- typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
-
-
- /***********************************************************************/
- /* */
- /* <Type> T1_CharMap */
- /* */
- /* <Description> */
- /* A handle to a Type 1 character mapping object. */
- /* */
- /* <Note> */
- /* The Type 1 format doesn't use a charmap but an encoding table. */
- /* The driver is responsible for making up charmap objects */
- /* corresponding to these tables.. */
- /* */
- typedef struct T1_CharMapRec_* T1_CharMap;
-
-
-
- /**************************************************************************/
- /* */
- /* NOW BEGINS THE TYPE1 SPECIFIC STUFF .............................. */
- /* */
- /**************************************************************************/
-
-
- /***************************************************/
- /* */
- /* T1_Size : */
- /* */
- /* Type 1 size record.. */
- /* */
-
- typedef struct T1_SizeRec_
- {
- FT_SizeRec root;
- FT_Bool valid;
- T1_Size_Hints* hints; /* defined in the hinter. This allows */
- /* us to experiment with different */
- /* hinting schemes without having to */
- /* change 't1objs' each time.. */
- } T1_SizeRec;
-
-
-
- /***************************************************/
- /* */
- /* T1_GlyphSlot : */
- /* */
- /* TrueDoc glyph record.. */
- /* */
-
- typedef struct T1_GlyphSlotRec_
- {
- FT_GlyphSlotRec root;
-
- FT_Bool hint;
- FT_Bool scaled;
-
- FT_Int max_points;
- FT_Int max_contours;
-
- FT_Fixed x_scale;
- FT_Fixed y_scale;
-
- T1_Glyph_Hints* hints; /* defined in the hinter */
-
- } T1_GlyphSlotRec;
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_Face
- *
- * <Description>
- * Initialise a given Type 1 face object
- *
- * <Input>
- * face_index :: index of font face in resource
- * resource :: source font resource
- * face :: face record to build
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_Face( FT_Stream stream,
- T1_Face face,
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Face
- *
- * <Description>
- * Finalise a given face object
- *
- * <Input>
- * face :: handle to the face object to destroy
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Face( T1_Face face );
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_Driver
- *
- * <Description>
- * Initialise a given Type 1 driver object
- *
- * <Input>
- * driver :: handle to target driver object
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_Driver( T1_Driver driver );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Driver
- *
- * <Description>
- * finalise a given Type 1 driver
- *
- * <Input>
- * driver :: handle to target Type 1 driver
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Driver( T1_Driver driver );
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* T1OBJS_H */
-
-
-/* END */
--- a/src/type1z/t1parse.c
+++ /dev/null
@@ -1,1269 +1,0 @@
-/*******************************************************************
- *
- * t1parse.c 2.0
- *
- * Type1 parser.
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- * The Type 1 parser is in charge of the following:
- *
- * - provide an implementation of a growing sequence of
- * objects called a T1_Table (used to build various tables
- * needed by the loader).
- *
- * - opening .pfb and .pfa files to extract their top-level
- * and private dictionaries
- *
- * - read numbers, arrays & strings from any dictionary
- *
- * See "t1load.c" to see how data is loaded from the font file
- *
- ******************************************************************/
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftcalc.h>
-#include <freetype/internal/ftobjs.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1errors.h>
-#include <t1parse.h>
-
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1load
-
-/*************************************************************************/
-/*************************************************************************/
-/*************************************************************************/
-/***** *****/
-/***** IMPLEMENTATION OF T1_TABLE OBJECT *****/
-/***** *****/
-/***** *****/
-/*************************************************************************/
-/*************************************************************************/
-/*************************************************************************/
-
-
-/*************************************************************************/
-/* */
-/* <Function> T1_New_Table */
-/* */
-/* <Description> */
-/* Initialise a T1_Table. */
-/* */
-/* <Input> */
-/* table :: address of target table */
-/* count :: table size = maximum number of elements */
-/* memory :: memory object to use for all subsequent reallocations */
-/* */
-/* <Return> */
-/* Error code. 0 means success */
-/* */
-
- LOCAL_FUNC
- FT_Error T1_New_Table( T1_Table* table,
- FT_Int count,
- FT_Memory memory )
- {
- FT_Error error;
-
- table->memory = memory;
- if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
- ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
- goto Exit;
-
- table->max_elems = count;
- table->init = 0xdeadbeef;
- table->num_elems = 0;
- table->block = 0;
- table->capacity = 0;
- table->cursor = 0;
-
- Exit:
- if (error) FREE(table->elements);
-
- return error;
- }
-
-
-
-/*************************************************************************/
-/* */
-/* <Function> T1_Add_Table */
-/* */
-/* <Description> */
-/* Adds an object to a T1_Table, possibly growing its memory block */
-/* */
-/* <Input> */
-/* table :: target table */
-/* index :: index of object in table */
-/* object :: address of object to copy in memory */
-/* length :: length in bytes of source object */
-/* */
-/* <Return> */
-/* Error code. 0 means success. An error is returned when a */
-/* realloc failed.. */
-/* */
-
-
- static void shift_elements( T1_Table* table, FT_Byte* old_base )
- {
- FT_Long delta = table->block - old_base;
- FT_Byte** offset = table->elements;
- FT_Byte** limit = offset + table->max_elems;
-
- if (delta)
- for ( ; offset < limit; offset++ )
- {
- if (offset[0])
- offset[0] += delta;
- }
- }
-
- static
- FT_Error reallocate_t1_table( T1_Table* table,
- FT_Int new_size )
- {
- FT_Memory memory = table->memory;
- FT_Byte* old_base = table->block;
- FT_Error error;
-
- /* realloc the base block */
- if ( REALLOC( table->block, table->capacity, new_size ) )
- return error;
-
- table->capacity = new_size;
-
- /* shift all offsets when needed */
- if (old_base)
- shift_elements( table, old_base );
-
- return T1_Err_Ok;
- }
-
-
-
- LOCAL_FUNC
- FT_Error T1_Add_Table( T1_Table* table,
- FT_Int index,
- void* object,
- FT_Int length )
- {
- if (index < 0 || index > table->max_elems)
- {
- FT_ERROR(( "T1.Add_Table: invalid index\n" ));
- return T1_Err_Syntax_Error;
- }
-
- /* grow the base block if needed */
- if ( table->cursor + length > table->capacity )
- {
- FT_Error error;
- FT_Int new_size = table->capacity;
-
- while ( new_size < table->cursor+length )
- new_size += 1024;
-
- error = reallocate_t1_table( table, new_size );
- if (error) return error;
- }
-
- /* add the object to the base block and adjust offset */
- table->elements[ index ] = table->block + table->cursor;
- table->lengths [ index ] = length;
- MEM_Copy( table->block + table->cursor, object, length );
-
- table->cursor += length;
- return T1_Err_Ok;
- }
-
-
-/*************************************************************************/
-/* */
-/* <Function> T1_Done_Table */
-/* */
-/* <Description> */
-/* Finalise a T1_Table. (realloc it to its current cursor). */
-/* */
-/* <Input> */
-/* table :: target table */
-/* */
-/* <Note> */
-/* This function does NOT release the heap's memory block. It is up */
-/* to the caller to clean it, or reference it in its own structures. */
-/* */
-#if 0
- LOCAL_FUNC
- void T1_Done_Table( T1_Table* table )
- {
- FT_Memory memory = table->memory;
- FT_Error error;
- FT_Byte* old_base;
-
- /* should never fail, as rec.cursor <= rec.size */
- old_base = table->block;
- if (!old_base)
- return;
-
- (void)REALLOC( table->block, table->capacity, table->cursor );
- table->capacity = table->cursor;
-
- if (old_base != table->block)
- shift_elements( table, old_base );
- }
-#endif
-
- LOCAL_FUNC
- void T1_Release_Table( T1_Table* table )
- {
- FT_Memory memory = table->memory;
-
- if (table->init == (FT_Long)0xdeadbeef)
- {
- FREE( table->block );
- FREE( table->elements );
- FREE( table->lengths );
- table->init = 0;
- }
- }
-
-/*************************************************************************/
-/*************************************************************************/
-/*************************************************************************/
-/***** *****/
-/***** INPUT STREAM PARSER *****/
-/***** *****/
-/***** *****/
-/*************************************************************************/
-/*************************************************************************/
-/*************************************************************************/
-
- #define IS_T1_WHITESPACE(c) ( (c) == ' ' || (c) == '\t' )
- #define IS_T1_LINESPACE(c) ( (c) == '\r' || (c) == '\n' )
-
- #define IS_T1_SPACE(c) ( IS_T1_WHITESPACE(c) || IS_T1_LINESPACE(c) )
-
- LOCAL_FUNC
- void T1_Skip_Spaces( T1_Parser* parser )
- {
- FT_Byte* cur = parser->cursor;
- FT_Byte* limit = parser->limit;
-
- while (cur < limit)
- {
- FT_Byte c = *cur;
- if (!IS_T1_SPACE(c))
- break;
- cur++;
- }
- parser->cursor = cur;
- }
-
- LOCAL_FUNC
- void T1_ToToken( T1_Parser* parser,
- T1_Token_Rec* token )
- {
- FT_Byte* cur;
- FT_Byte* limit;
- FT_Byte starter, ender;
- FT_Int embed;
-
- token->type = t1_token_none;
- token->start = 0;
- token->limit = 0;
-
- /* first of all, skip space */
- T1_Skip_Spaces(parser);
-
- cur = parser->cursor;
- limit = parser->limit;
-
- if ( cur < limit )
- {
- switch (*cur)
- {
- /************* check for strings ***********************/
- case '(':
- token->type = t1_token_string;
- ender = ')';
- goto Lookup_Ender;
-
- /************* check for programs/array ****************/
- case '{':
- token->type = t1_token_array;
- ender = '}';
- goto Lookup_Ender;
-
- /************* check for table/array ******************/
- case '[':
- token->type = t1_token_array;
- ender = ']';
-
- Lookup_Ender:
- embed = 1;
- starter = *cur++;
- token->start = cur;
- while (cur < limit)
- {
- if (*cur == starter)
- embed++;
- else if (*cur == ender)
- {
- embed--;
- if (embed <= 0)
- {
- token->limit = cur++;
- break;
- }
- }
- cur++;
- }
- break;
-
- /* **************** otherwise, it's any token **********/
- default:
- token->start = cur++;
- token->type = t1_token_any;
- while (cur < limit && !IS_T1_SPACE(*cur))
- cur++;
-
- token->limit = cur;
- }
-
- if (!token->limit)
- {
- token->start = 0;
- token->type = t1_token_none;
- }
-
- parser->cursor = cur;
- }
- }
-
-
- LOCAL_FUNC
- void T1_ToTokenArray( T1_Parser* parser,
- T1_Token_Rec* tokens,
- FT_UInt max_tokens,
- FT_Int *pnum_tokens )
- {
- T1_Token_Rec master;
-
- *pnum_tokens = -1;
-
- T1_ToToken( parser, &master );
- if (master.type == t1_token_array)
- {
- FT_Byte* old_cursor = parser->cursor;
- FT_Byte* old_limit = parser->limit;
- T1_Token_Rec* cur = tokens;
- T1_Token_Rec* limit = cur + max_tokens;
-
- parser->cursor = master.start;
- parser->limit = master.limit;
-
- while (parser->cursor < parser->limit)
- {
- T1_Token_Rec token;
-
- T1_ToToken( parser, &token );
- if (!token.type)
- break;
-
- if (cur < limit)
- *cur = token;
-
- cur++;
- }
-
- *pnum_tokens = cur - tokens;
-
- parser->cursor = old_cursor;
- parser->limit = old_limit;
- }
- }
-
-
- static
- FT_Long t1_toint( FT_Byte* *cursor,
- FT_Byte* limit )
- {
- FT_Long result = 0;
- FT_Byte* cur = *cursor;
- FT_Byte c, d;
-
- for (; cur < limit; cur++)
- {
- c = *cur;
- d = (FT_Byte)(c - '0');
- if (d < 10) break;
-
- if ( c=='-' )
- {
- cur++;
- break;
- }
- }
-
- if (cur < limit)
- {
- do
- {
- d = (FT_Byte)(cur[0] - '0');
- if (d >= 10)
- break;
-
- result = result*10 + d;
- cur++;
-
- } while (cur < limit);
-
- if (c == '-')
- result = -result;
- }
-
- *cursor = cur;
- return result;
- }
-
-
- static
- FT_Long t1_tofixed( FT_Byte* *cursor,
- FT_Byte* limit,
- FT_Long power_ten )
- {
- FT_Byte* cur = *cursor;
- FT_Long num, divider, result;
- FT_Int sign = 0;
- FT_Byte d;
-
- if (cur >= limit) return 0;
-
- /* first of all, read the integer part */
- result = t1_toint( &cur, limit ) << 16;
- num = 0;
- divider = 1;
-
- if (result < 0)
- {
- sign = 1;
- result = -result;
- }
- if (cur >= limit) goto Exit;
-
- /* read decimal part, if any */
- if (*cur == '.' && cur+1 < limit)
- {
- cur++;
-
- for (;;)
- {
- d = (FT_Byte)(*cur - '0');
- if (d >= 10) break;
-
- if (divider < 10000000L)
- {
- num = num*10 + d;
- divider *= 10;
- }
- cur++;
- if (cur >= limit) break;
- }
- }
-
- /* read exponent, if any */
- if ( cur+1 < limit && (*cur == 'e' || *cur == 'E'))
- {
- cur++;
- power_ten += t1_toint( &cur, limit );
- }
-
- Exit:
- /* raise to power of ten if needed */
- while (power_ten > 0)
- {
- result = result*10;
- num = num*10;
- power_ten--;
- }
-
- while (power_ten < 0)
- {
- result = result/10;
- divider = divider*10;
- power_ten++;
- }
-
- if (num)
- result += FT_DivFix( num, divider );
-
- if (sign)
- result = -result;
-
- *cursor = cur;
- return result;
- }
-
-
- static
- FT_Int t1_tocoordarray( FT_Byte* *cursor,
- FT_Byte* limit,
- FT_Int max_coords,
- FT_Short* coords )
- {
- FT_Byte* cur = *cursor;
- FT_Int count = 0;
- FT_Byte c, ender;
-
- if (cur >= limit) goto Exit;
-
- /* check for the beginning of an array. If not, only one number will be read */
- c = *cur;
- ender = 0;
-
- if (c == '[')
- ender = ']';
-
- if (c == '{')
- ender = '}';
-
- if (ender)
- cur++;
-
- /* now, read the coordinates */
- for ( ; cur < limit; )
- {
- /* 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;
-
- coords[count] = (FT_Short)(t1_tofixed(&cur,limit,0) >> 16);
- count++;
-
- if (!ender)
- break;
- }
-
- Exit:
- *cursor = cur;
- return count;
- }
-
-
-
- static
- FT_Int t1_tofixedarray( FT_Byte* *cursor,
- FT_Byte* limit,
- FT_Int max_values,
- FT_Fixed* values,
- FT_Int power_ten )
- {
- FT_Byte* cur = *cursor;
- FT_Int count = 0;
- FT_Byte c, ender;
-
- if (cur >= limit) goto Exit;
-
- /* check for the beginning of an array. If not, only one number will be read */
- c = *cur;
- ender = 0;
-
- if (c == '[')
- ender = ']';
-
- if (c == '{')
- ender = '}';
-
- if (ender)
- cur++;
-
- /* now, read the values */
- for ( ; cur < limit; )
- {
- /* 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;
-
- values[count] = t1_tofixed(&cur,limit,power_ten);
- count++;
-
- if (!ender)
- break;
- }
-
- Exit:
- *cursor = cur;
- return count;
- }
-
-
-#if 0
- static
- FT_String* t1_tostring( FT_Byte* *cursor, FT_Byte* limit, FT_Memory memory )
- {
- FT_Byte* cur = *cursor;
- FT_Int len = 0;
- FT_Int count;
- FT_String* result;
- FT_Error error;
-
- /* 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;
-
- /* then, count its length */
- for ( ; cur < limit; cur++ )
- {
- if (*cur == '(')
- count++;
-
- else if (*cur == ')')
- {
- count--;
- if (count < 0)
- break;
- }
- }
-
- len = cur - *cursor;
- if (cur >= limit || ALLOC(result,len+1)) return 0;
-
- /* now copy the string */
- MEM_Copy( result, *cursor, len );
- result[len] = '\0';
- *cursor = cur;
- return result;
- }
-#endif
-
- static
- int t1_tobool( FT_Byte* *cursor, FT_Byte* limit )
- {
- FT_Byte* cur = *cursor;
- FT_Bool result = 0;
-
- /* return 1 if we find a "true", 0 otherwise */
- if ( cur+3 < limit &&
- cur[0] == 't' &&
- cur[1] == 'r' &&
- cur[2] == 'u' &&
- cur[3] == 'e' )
- {
- result = 1;
- cur += 5;
- }
- else if ( cur+4 < limit &&
- cur[0] == 'f' &&
- cur[1] == 'a' &&
- cur[2] == 'l' &&
- cur[3] == 's' &&
- cur[4] == 'e' )
- {
- result = 0;
- cur += 6;
- }
- *cursor = cur;
- return result;
- }
-
-
-
- /* Loads a simple field (i.e. non-table) into the current list of objects */
- LOCAL_FUNC
- FT_Error T1_Load_Field( T1_Parser* parser,
- const T1_Field_Rec* field,
- void** objects,
- FT_UInt max_objects,
- FT_ULong* pflags )
- {
- T1_Token_Rec token;
- FT_Byte* cur;
- FT_Byte* limit;
- FT_UInt count;
- FT_UInt index;
- FT_Error error;
-
- T1_ToToken( parser, &token );
- if (!token.type)
- goto Fail;
-
- count = 1;
- index = 0;
- cur = token.start;
- limit = token.limit;
-
- if (token.type == t1_token_array)
- {
- /* if this is an array, and we have no blend, an error occurs */
- if (max_objects == 0)
- goto Fail;
-
- count = max_objects;
- index = 1;
- }
-
- for ( ; count > 0; count--, index++ )
- {
- FT_Byte* q = (FT_Byte*)objects[index] + field->offset;
- FT_Long val;
- FT_String* string;
-
- switch (field->type)
- {
- case t1_field_bool:
- {
- val = t1_tobool( &cur, limit );
- goto Store_Integer;
- }
-
- case t1_field_fixed:
- {
- val = t1_tofixed( &cur, limit, 3 );
- goto Store_Integer;
- }
-
- case t1_field_integer:
- {
- val = t1_toint( &cur, limit );
- Store_Integer:
- switch (field->size)
- {
- case 1: *(FT_Byte*)q = (FT_Byte)val; break;
- case 2: *(FT_UShort*)q = (FT_UShort)val; break;
- default: *(FT_Long*)q = val;
- }
- }
- break;
-
- case t1_field_string:
- {
- FT_Memory memory = parser->memory;
- FT_UInt len = limit-cur;
-
- if ( ALLOC( string, len+1 ) )
- goto Exit;
-
- MEM_Copy( string, cur, len );
- string[len] = 0;
-
- *(FT_String**)q = string;
- }
- break;
-
- default:
- /* an error occured */
- goto Fail;
- }
- }
- if (pflags)
- *pflags |= 1L << field->flag_bit;
- error = 0;
-
- Exit:
- return error;
- Fail:
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
-
-#define T1_MAX_TABLE_ELEMENTS 32
-
- LOCAL_FUNC
- FT_Error T1_Load_Field_Table( T1_Parser* parser,
- const T1_Field_Rec* field,
- void** objects,
- FT_UInt max_objects,
- FT_ULong* pflags )
- {
- T1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
- T1_Token_Rec* token;
- FT_Int num_elements;
- FT_Error error = 0;
- FT_Byte* old_cursor;
- FT_Byte* old_limit;
- T1_Field_Rec fieldrec = *(T1_Field_Rec*)field;
-
- T1_ToTokenArray( parser, elements, 32, &num_elements );
- if (num_elements < 0)
- goto Fail;
-
- if (num_elements > T1_MAX_TABLE_ELEMENTS)
- num_elements = T1_MAX_TABLE_ELEMENTS;
-
- old_cursor = parser->cursor;
- old_limit = parser->limit;
-
- /* we store the elements count */
- *(FT_Byte*)((FT_Byte*)objects[0] + field->count_offset) = num_elements;
-
- /* we now load each element, adjusting the field.offset on each one */
- token = elements;
- for ( ; num_elements > 0; num_elements--, token++ )
- {
- parser->cursor = token->start;
- parser->limit = token->limit;
- T1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
- fieldrec.offset += fieldrec.size;
- }
-
- if (pflags)
- *pflags |= 1L << field->flag_bit;
-
- parser->cursor = old_cursor;
- parser->limit = old_limit;
-
- Exit:
- return error;
- Fail:
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
-
-
-
-
-
-
- LOCAL_FUNC
- FT_Long T1_ToInt ( T1_Parser* parser )
- {
- return t1_toint( &parser->cursor, parser->limit );
- }
-
-
- LOCAL_FUNC
- FT_Long T1_ToFixed( T1_Parser* parser, FT_Int power_ten )
- {
- return t1_tofixed( &parser->cursor, parser->limit, power_ten );
- }
-
-
- LOCAL_FUNC
- FT_Int T1_ToCoordArray( T1_Parser* parser,
- FT_Int max_coords,
- FT_Short* coords )
- {
- return t1_tocoordarray( &parser->cursor, parser->limit, max_coords, coords );
- }
-
-
- LOCAL_FUNC
- FT_Int T1_ToFixedArray( T1_Parser* parser,
- FT_Int max_values,
- FT_Fixed* values,
- FT_Int power_ten )
- {
- return t1_tofixedarray( &parser->cursor, parser->limit, max_values, values, power_ten );
- }
-
-
-#if 0
- LOCAL_FUNC
- FT_String* T1_ToString( T1_Parser* parser )
- {
- return t1_tostring( &parser->cursor, parser->limit, parser->memory );
- }
-
-
- LOCAL_FUNC
- FT_Bool T1_ToBool( T1_Parser* parser )
- {
- return t1_tobool( &parser->cursor, parser->limit );
- }
-#endif
-
-
- static
- FT_Error read_pfb_tag( FT_Stream stream, FT_UShort *tag, FT_Long* size )
- {
- FT_Error error;
-
- if (READ_UShort(*tag)) goto Exit;
- if (*tag == 0x8001 || *tag == 0x8002)
- {
- FT_Long asize;
-
- if (READ_ULong(asize)) goto Exit;
-
- /* swap between big and little endianness */
- *size = ((asize & 0xFF000000) >> 24) |
- ((asize & 0x00FF0000) >> 8 ) |
- ((asize & 0x0000FF00) << 8 ) |
- ((asize & 0x000000FF) << 24);
- }
-
- Exit:
- return error;
- }
-
-
-
- LOCAL_FUNC
- FT_Error T1_New_Parser( T1_Parser* parser,
- FT_Stream stream,
- FT_Memory memory )
- {
- FT_Error error;
- FT_UShort tag;
- FT_Long size;
-
- parser->stream = stream;
- parser->memory = memory;
- parser->base_len = 0;
- parser->base_dict = 0;
- parser->private_len = 0;
- parser->private_dict = 0;
- parser->in_pfb = 0;
- parser->in_memory = 0;
- parser->single_block = 0;
-
- parser->cursor = 0;
- parser->limit = 0;
-
- /******************************************************************/
- /* */
- /* Here's a short summary of what is going on : */
- /* */
- /* When creating a new Type 1 parser, we try to locate and */
- /* load the base dictionary when this is possible (i.e. for */
- /* .pfb files). Otherwise, we load the whole font in memory. */
- /* */
- /* When "loading" the base dictionary, we only setup pointers */
- /* in the case of a memory-based stream. Otherwise, we allocate */
- /* and load the base dict in it. */
- /* */
- /* parser->in_pfb is set when we are in a binary (".pfb") font */
- /* parser->in_memory is set when we have a memory stream. */
- /* */
-
- /* try to compute the size of the base dictionary */
- /* look for a Postscript binary file tag, i.e 0x8001 */
- if ( FILE_Seek(0L) )
- goto Exit;
-
- error = read_pfb_tag( stream, &tag, &size );
- if (error) goto Exit;
-
- if (tag != 0x8001)
- {
- /* assume that this is a PFA file for now, an error will */
- /* be produced later when more things are checked */
- (void)FILE_Seek(0L);
- size = stream->size;
- }
- 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 = (FT_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 = FT_Err_Unknown_File_Format;
- }
- else
- {
- parser->cursor = parser->base_dict;
- parser->limit = parser->cursor + parser->base_len;
- }
- }
-
- Exit:
- if (error && !parser->in_memory)
- FREE( parser->base_dict );
-
- return error;
- }
-
-
- LOCAL_FUNC
- void T1_Done_Parser( T1_Parser* parser )
- {
- FT_Memory memory = parser->memory;
-
- /* always free the private dictionary */
- FREE( parser->private_dict );
-
- /* free the base dictionary only when we have a disk stream */
- if (!parser->in_memory)
- FREE( parser->base_dict );
- }
-
-
- /* return the value of an hexadecimal digit */
- static
- int hexa_value( char c )
- {
- unsigned int d;
-
- d = (unsigned int)(c-'0');
- if ( d <= 9 ) return (int)d;
-
- d = (unsigned int)(c-'a');
- if ( d <= 5 ) return (int)(d+10);
-
- d = (unsigned int)(c-'A');
- if ( d <= 5 ) return (int)(d+10);
-
- return -1;
- }
-
-
- LOCAL_FUNC
- void T1_Decrypt( FT_Byte* buffer,
- FT_Int length,
- FT_UShort seed )
- {
- while ( length > 0 )
- {
- FT_Byte plain;
-
- plain = (*buffer ^ (seed >> 8));
- seed = (*buffer+seed)*52845+22719;
- *buffer++ = plain;
- length--;
- }
- }
-
-
- LOCAL_FUNC
- FT_Error T1_Get_Private_Dict( T1_Parser* parser )
- {
- FT_Stream stream = parser->stream;
- FT_Memory memory = parser->memory;
- FT_Error error = 0;
- FT_Long size;
-
- if (parser->in_pfb)
- {
- /* in the case of the PFB format, the private dictionary can be */
- /* made of several segments. We thus first read the number of */
- /* segments to compute the total size of the private dictionary */
- /* then re-read them into memory.. */
- FT_Long start_pos = FILE_Pos();
- FT_UShort tag;
- FT_Long size;
-
- parser->private_len = 0;
- for (;;)
- {
- error = read_pfb_tag(stream, &tag, &size);
- if (error) goto Fail;
-
- if (tag != 0x8002)
- break;
-
- parser->private_len += size;
-
- if ( FILE_Skip(size) )
- goto Fail;
- }
-
- /* Check that we have a private dictionary there */
- /* and allocate private dictionary buffer */
- if ( parser->private_len == 0 )
- {
- FT_ERROR(( "T1.Open_Private: invalid private dictionary section\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Fail;
- }
-
- if ( FILE_Seek( start_pos ) ||
- ALLOC( parser->private_dict, parser->private_len ) )
- goto Fail;
-
- parser->private_len = 0;
- for (;;)
- {
- error = read_pfb_tag( stream, &tag, &size );
- if (error || tag != 0x8002) { error = 0; break; }
-
- if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
- goto Fail;
-
- parser->private_len += size;
- }
- }
- else
- {
- /* we have already "loaded" the whole PFA font file in memory */
- /* if this is a memory resource, allocate a new block to hold */
- /* the private dict. Otherwise, simply overwrite into the */
- /* base dict block in the heap.. */
-
- /* first of all, look at the "eexec" keyword */
- FT_Byte* cur = parser->base_dict;
- FT_Byte* limit = cur + parser->base_len;
- FT_Byte c;
-
- for (;;)
- {
- c = cur[0];
- if (c == 'e' && cur+9 < limit) /* 9 = 5 letters for 'eexec' + newline + 4 chars */
- {
- if ( cur[1] == 'e' && cur[2] == 'x' &&
- cur[3] == 'e' && cur[4] == 'c' )
- {
- cur += 6; /* we skip the newling after the "eexec" */
-
- /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n, we need to skip */
- /* the extra \n when we find it.. */
- if (cur[0] == '\n')
- cur++;
-
- break;
- }
- }
- cur++;
- if (cur >= limit)
- {
- FT_ERROR(("T1.Open_Private: could not find 'eexec' keyword\n"));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
- }
-
- /* now determine wether where to write the _encrypted_ binary private */
- /* dictionary. We overwrite the base dictionary for disk-based resources */
- /* and allocate a new block otherwise */
-
- size = parser->base_len - (cur-parser->base_dict);
-
- if ( parser->in_memory )
- {
- /* note that we allocate one more byte to put a terminating '0' */
- if (ALLOC( parser->private_dict, size+1 )) goto Fail;
- parser->private_len = size;
- }
- else
- {
- parser->single_block = 1;
- parser->private_dict = parser->base_dict;
- parser->private_len = size;
- parser->base_dict = 0;
- parser->base_len = 0;
- }
-
- /* now determine wether the private dictionary is encoded in binary */
- /* or hexadecimal ASCII format.. */
- /* and decode it accordingly */
-
- /* we need to access the next 4 bytes (after the final \r following */
- /* the 'eexec' keyword..) if they all are hexadecimal digits, then */
- /*we have a case of ASCII storage.. */
-
- if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
- hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
- {
- /* binary encoding - "simply" copy the private dict */
- MEM_Copy( parser->private_dict, cur, size );
- }
- else
- {
- /* ASCII hexadecimal encoding.. This blows goats !!.. */
-
- FT_Byte* write;
- FT_Int count;
-
- write = parser->private_dict;
- count = 0;
-
- for ( ;cur < limit; cur++)
- {
- int hex1;
-
- /* check for newline */
- if (cur[0] == '\r' || cur[0] == '\n')
- continue;
-
- /* exit if we have a non-hexadecimal digit that isn't a newline */
- hex1 = hexa_value(cur[0]);
- if (hex1 < 0 || cur+1 >= limit)
- break;
-
- /* otherwise, store byte */
- *write++ = (hex1 << 4) | hexa_value(cur[1]);
- count++;
- cur++;
- }
-
- /* put a safeguard */
- parser->private_len = write - parser->private_dict;
- *write++ = 0;
- }
- }
-
- /* we now decrypt the encoded binary private dictionary */
- T1_Decrypt( parser->private_dict, parser->private_len, 55665 );
- parser->cursor = parser->private_dict;
- parser->limit = parser->cursor + parser->private_len;
-
- Fail:
- Exit:
- return error;
- }
-
--- a/src/type1z/t1parse.h
+++ /dev/null
@@ -1,348 +1,0 @@
-/*******************************************************************
- *
- * t1parse.h 2.0
- *
- * Type1 parser.
- *
- * Copyright 1996-1998 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- * The Type 1 parser is in charge of the following:
- *
- * - provide an implementation of a growing sequence of
- * objects called a T1_Table (used to build various tables
- * needed by the loader).
- *
- * - opening .pfb and .pfa files to extract their top-level
- * and private dictionaries
- *
- * - read numbers, arrays & strings from any dictionary
- *
- * See "t1load.c" to see how data is loaded from the font file
- *
- ******************************************************************/
-
-#ifndef T1PARSE_H
-#define T1PARSE_H
-
-#include <freetype/internal/t1types.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- /* simple enumeration type used to identify token types */
- typedef enum T1_Token_Type_
- {
- t1_token_none = 0,
- t1_token_any,
- t1_token_string,
- t1_token_array,
-
- /* do not remove */
- t1_token_max
-
- } T1_Token_Type;
-
- /* a simple structure used to identify tokens */
- typedef struct T1_Token_Rec_
- {
- FT_Byte* start; /* first character of token in input stream */
- FT_Byte* limit; /* first character after the token */
- T1_Token_Type type; /* type of token.. */
-
- } T1_Token_Rec;
-
- /* enumeration type used to identify object fields */
- typedef enum T1_Field_Type_
- {
- t1_field_none = 0,
- t1_field_bool,
- t1_field_integer,
- t1_field_fixed,
- t1_field_string,
- t1_field_integer_array,
- t1_field_fixed_array,
-
- /* do not remove */
- t1_field_max
-
- } T1_Field_Type;
-
- /* structure type used to model object fields */
- typedef struct T1_Field_Rec_
- {
- T1_Field_Type type; /* type of field */
- FT_UInt offset; /* offset of field in object */
- FT_UInt size; /* size of field in bytes */
- FT_UInt array_max; /* maximum number of elements for array */
- FT_UInt count_offset; /* offset of element count for arrays */
- FT_Int flag_bit; /* bit number for field flag */
-
- } T1_Field_Rec;
-
-#define T1_FIELD_REF(s,f) (((s*)0)->f)
-
-#define T1_FIELD_BOOL( _ftype, _fname ) \
- { t1_field_bool, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)), \
- 0, 0, 0 }
-
-#define T1_FIELD_NUM( _ftype, _fname ) \
- { t1_field_integer, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)), \
- 0, 0, 0 }
-
-#define T1_FIELD_FIXED( _ftype, _fname, _power ) \
- { t1_field_fixed, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)), \
- 0, 0, 0 }
-
-#define T1_FIELD_STRING( _ftype, _fname ) \
- { t1_field_string, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)), \
- 0, 0, 0 }
-
-#define T1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \
- { t1_field_integer, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
- _fmax, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fcount), \
- 0 }
-
-#define T1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \
- { t1_field_fixed, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
- _fmax, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fcount), \
- 0 }
-
-#define T1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \
- { t1_field_integer, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
- _fmax, \
- 0, 0 }
-
-#define T1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \
- { t1_field_fixed, \
- (FT_UInt)(char*)&T1_FIELD_REF(_ftype,_fname), \
- sizeof(T1_FIELD_REF(_ftype,_fname)[0]), \
- _fmax, \
- 0, 0 }
-
-
-
-/*************************************************************************
- *
- * <Struct> T1_Table
- *
- * <Description>
- * A T1_Table is a simple object used to store an array of objects
- * in a single memory block.
- *
- * <Fields>
- * block :: address in memory of the growheap's block. This
- * can change between two object adds, due to the use
- * of 'realloc'.
- *
- * cursor :: current top of the grow heap within its block
- *
- * capacity :: current size of the heap block. Increments by 1 Kb
- *
- * init :: boolean. set when the table has been initialized
- * (the table user should set this field)
- *
- * max_elems :: maximum number of elements in table
- * num_elems :: current number of elements in table
- *
- * elements :: table of element addresses within the block
- * lengths :: table of element sizes within the block
- *
- * memory :: memory object used for memory operations (alloc/realloc)
- */
-
- typedef struct T1_Table_
- {
- FT_Byte* block; /* current memory block */
- FT_Int cursor; /* current cursor in memory block */
- FT_Int capacity; /* current size of memory block */
- FT_Long init;
-
- FT_Int max_elems;
- FT_Int num_elems;
- FT_Byte** elements; /* addresses of table elements */
- FT_Int* lengths; /* lengths of table elements */
-
- FT_Memory memory;
-
- } T1_Table;
-
-
-/*************************************************************************
- *
- * <Struct> T1_Parser
- *
- * <Description>
- * A T1_Parser is an object used to parse a Type 1 fonts very
- * quickly.
- *
- * <Fields>
- * stream :: current input stream
- * memory :: current memory object
- *
- * base_dict :: pointer to top-level dictionary
- * base_len :: length in bytes of top dict
- *
- * private_dict :: pointer to private dictionary
- * private_len :: length in bytes of private dict
- *
- * in_pfb :: boolean. Indicates that we're in a .pfb file
- * in_memory :: boolean. Indicates a memory-based stream
- * single_block :: boolean. Indicates that the private dict
- * is stored in lieu of the base dict
- *
- * cursor :: current parser cursor
- * limit :: current parser limit (first byte after current
- * dictionary).
- *
- * error :: current parsing error
- */
- typedef struct T1_Parser_
- {
- FT_Stream stream;
- FT_Memory memory;
-
- FT_Byte* base_dict;
- FT_Int base_len;
-
- FT_Byte* private_dict;
- FT_Int private_len;
-
- FT_Byte in_pfb;
- FT_Byte in_memory;
- FT_Byte single_block;
-
- FT_Byte* cursor;
- FT_Byte* limit;
- FT_Error error;
-
- } T1_Parser;
-
-
- LOCAL_DEF
- FT_Error T1_New_Table( T1_Table* table,
- FT_Int count,
- FT_Memory memory );
-
-
- LOCAL_DEF
- FT_Error T1_Add_Table( T1_Table* table,
- FT_Int index,
- void* object,
- FT_Int length );
-
-#if 0
- LOCAL_DEF
- void T1_Done_Table( T1_Table* table );
-#endif
-
- LOCAL_DEF
- void T1_Release_Table( T1_Table* table );
-
- LOCAL_DEF
- FT_Long T1_ToInt ( T1_Parser* parser );
-
- LOCAL_DEF
- FT_Long T1_ToFixed( T1_Parser* parser, FT_Int power_ten );
-
- LOCAL_DEF
- FT_Int T1_ToCoordArray( T1_Parser* parser,
- FT_Int max_coords,
- FT_Short* coords );
-
- LOCAL_DEF
- FT_Int T1_ToFixedArray( T1_Parser* parser,
- FT_Int max_values,
- FT_Fixed* values,
- FT_Int power_ten );
-
-#if 0
- LOCAL_DEF
- FT_String* T1_ToString( T1_Parser* parser );
-
- LOCAL_DEF
- FT_Bool T1_ToBool( T1_Parser* parser );
-#endif
-
-
-
-
-
-
- LOCAL_DEF
- void T1_Skip_Spaces( T1_Parser* parser );
-
- LOCAL_DEF
- void T1_ToToken( T1_Parser* parser,
- T1_Token_Rec* token );
-
- LOCAL_FUNC
- void T1_ToTokenArray( T1_Parser* parser,
- T1_Token_Rec* tokens,
- FT_UInt max_tokens,
- FT_Int* pnum_tokens );
-
- LOCAL_DEF
- FT_Error T1_Load_Field( T1_Parser* parser,
- const T1_Field_Rec* field,
- void** objects,
- FT_UInt max_objects,
- FT_ULong* pflags );
-
- LOCAL_DEF
- FT_Error T1_Load_Field_Table( T1_Parser* parser,
- const T1_Field_Rec* field,
- void** objects,
- FT_UInt max_objects,
- FT_ULong* pflags );
-
-
- LOCAL_DEF
- FT_Error T1_New_Parser( T1_Parser* parser,
- FT_Stream stream,
- FT_Memory memory );
-
- LOCAL_DEF
- FT_Error T1_Get_Private_Dict( T1_Parser* parser );
-
- LOCAL_DEF
- void T1_Decrypt( FT_Byte* buffer,
- FT_Int length,
- FT_UShort seed );
-
- LOCAL_DEF
- void T1_Done_Parser( T1_Parser* parser );
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* T1PARSE_H */
-
-
-/* END */
-
--- a/src/type1z/t1tokens.h
+++ /dev/null
@@ -1,125 +1,0 @@
-/*******************************************************************
- *
- * t1tokens.h
- *
- * Type 1 tokens definition
- *
- * Copyright 2000 David Turner, Robert Wilhelm and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used
- * modified and distributed under the terms of the FreeType project
- * license, LICENSE.TXT. By continuing to use, modify or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- * This file only contains macros that are expanded when compiling
- * the "t1load.c" source file.
- *
- ******************************************************************/
-
-#undef T1TYPE
-#define T1TYPE T1_FontInfo
-
- T1_FONTINFO_STRING( "version", version )
- T1_FONTINFO_STRING( "Notice", notice )
- T1_FONTINFO_STRING( "FullName", full_name )
- T1_FONTINFO_STRING( "FamilyName", family_name )
- T1_FONTINFO_STRING( "Weight", weight )
-
- T1_FONTINFO_NUM( "ItalicAngle", italic_angle )
- T1_FONTINFO_BOOL( "isFixedPitch", is_fixed_pitch )
- T1_FONTINFO_NUM( "UnderlinePosition", underline_position )
- T1_FONTINFO_NUM( "UnderlineThickness", underline_thickness )
-
-#undef T1TYPE
-#define T1TYPE T1_Private
-
- T1_PRIVATE_NUM ( "UniqueID", unique_id )
- T1_PRIVATE_NUM ( "lenIV", lenIV )
- T1_PRIVATE_NUM ( "LanguageGroup", language_group )
- T1_PRIVATE_NUM ( "password", password )
-
- T1_PRIVATE_FIXED( "BlueScale", blue_scale )
- T1_PRIVATE_NUM ( "BlueShift", blue_shift )
- T1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz )
-
- T1_PRIVATE_NUM_TABLE( "BlueValues", blue_values, 14, num_blue_values )
- T1_PRIVATE_NUM_TABLE( "OtherBlues", other_blues, 10, num_other_blues )
- T1_PRIVATE_NUM_TABLE( "FamilyBlues", family_blues, 14, num_family_blues )
- T1_PRIVATE_NUM_TABLE( "FamilyOtherBlues", family_other_blues, 10, num_family_other_blues )
-
- T1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 )
- T1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
- T1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
-
- T1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths )
- T1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights )
-
-#undef T1TYPE
-#define T1TYPE T1_Font
-
- T1_TOPDICT_NUM( "PaintType", paint_type )
- T1_TOPDICT_NUM( "FontType", font_type )
- T1_TOPDICT_NUM( "StrokeWidth", stroke_width )
-
-#if 0
- /* define the font info dictionary parsing callbacks */
-#undef FACE
-#define FACE (face->type1.font_info)
-
- PARSE_STRING("version",version)
- PARSE_STRING("Notice",notice)
- PARSE_STRING("FullName",full_name)
- PARSE_STRING("FamilyName",family_name)
- PARSE_STRING("Weight",weight)
-
- PARSE_INT("ItalicAngle",italic_angle)
- PARSE_BOOL("isFixedPitch",is_fixed_pitch)
- PARSE_NUM("UnderlinePosition",underline_position,FT_Short)
- PARSE_NUM("UnderlineThickness",underline_thickness,FT_UShort)
-
- /* define the private dict parsing callbacks */
-
-#undef FACE
-#define FACE (face->type1.private_dict)
-
- PARSE_INT("UniqueID",unique_id)
- PARSE_INT("lenIV",lenIV)
-
- PARSE_COORDS( "BlueValues", num_blues, 14, blue_values)
- PARSE_COORDS( "OtherBlues", num_other_blues, 10, other_blues)
-
- PARSE_COORDS( "FamilyBlues", num_family_blues, 14, family_blues)
- PARSE_COORDS( "FamilyOtherBlues", num_family_other_blues, 10, family_other_blues)
-
- PARSE_FIXED( "BlueScale", blue_scale)
- PARSE_INT( "BlueShift", blue_shift)
-
- PARSE_INT( "BlueFuzz", blue_fuzz)
-
- PARSE_COORDS2( "StdHW", 1, standard_width )
- PARSE_COORDS2( "StdVW", 1, standard_height )
-
- PARSE_COORDS( "StemSnapH", num_snap_widths, 12, stem_snap_widths )
- PARSE_COORDS( "StemSnapV", num_snap_heights, 12, stem_snap_heights )
-
- PARSE_INT( "LanguageGroup", language_group )
- PARSE_INT( "password", password )
- PARSE_COORDS2( "MinFeature", 2, min_feature )
-
- /* define the top-level dictionary parsing callbacks */
-
-#undef FACE
-#define FACE (face->type1)
-
-
-/* PARSE_STRING( "FontName", font_name ) -- handled by special routine */
- PARSE_NUM( "PaintType", paint_type, FT_Byte )
- PARSE_NUM( "FontType", font_type, FT_Byte )
- PARSE_FIXEDS2( "FontMatrix", 4, font_matrix )
-/* PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special func */
- PARSE_INT( "StrokeWidth", stroke_width )
-
-#undef FACE
-#endif
-
--- a/src/type1z/type1z.c
+++ b/src/type1z/type1z.c
@@ -29,13 +29,13 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
-#include <t1parse.c>
-#include <t1load.c>
-#include <t1objs.c>
-#include <t1driver.c>
-#include <t1gload.c>
+#include <z1parse.c>
+#include <z1load.c>
+#include <z1objs.c>
+#include <z1driver.c>
+#include <z1gload.c>
-#ifndef T1_CONFIG_OPTION_NO_AFM
-#include <t1afm.c>
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+#include <z1afm.c>
#endif
--- /dev/null
+++ b/src/type1z/z1afm.c
@@ -1,0 +1,229 @@
+/***************************************************************************
+ *
+ * t1afm.c - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#include <z1afm.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <stdlib.h> /* for qsort */
+
+ LOCAL_FUNC
+ void Z1_Done_AFM( FT_Memory memory, Z1_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[n];
+
+ 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;
+ int sign = 1;
+
+ /* skip everything that is not a number */
+ while ( p < limit && (*p < '0' || *p > '9') )
+ {
+ sign = 1;
+ if (*p == '-')
+ sign = -1;
+
+ p++;
+ }
+
+ while ( p < limit && (*p >= '0' && *p < '9') )
+ {
+ sum = sum*10 + (*p - '0');
+ p++;
+ }
+ *start = p;
+ return sum*sign;
+ }
+
+
+#undef KERN_INDEX
+#define KERN_INDEX(g1,g2) (((FT_ULong)g1 << 16) | g2)
+
+ /* compare two kerning pairs */
+ static
+ int compare_kern_pairs( const void* a, const void* b )
+ {
+ Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a;
+ Z1_Kern_Pair* pair2 = (Z1_Kern_Pair*)b;
+
+ FT_ULong index1 = KERN_INDEX(pair1->glyph1,pair1->glyph2);
+ FT_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 Z1_Read_AFM( FT_Face t1_face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* p;
+ FT_Int count = 0;
+ Z1_Kern_Pair* pair;
+ T1_Font* type1 = &((T1_Face)t1_face)->type1;
+ Z1_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, Z1_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(Z1_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 Z1_Get_Kerning( Z1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ Z1_Kern_Pair *min, *mid, *max;
+ FT_ULong index = KERN_INDEX(glyph1,glyph2);
+
+ /* simple binary search */
+ min = afm->kern_pairs;
+ max = min + afm->num_pairs-1;
+
+ while (min <= max)
+ {
+ FT_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/z1afm.h
@@ -1,0 +1,50 @@
+/***************************************************************************
+ *
+ * t1afm.h - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.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 Z1_Kern_Pair_
+{
+ FT_UInt glyph1;
+ FT_UInt glyph2;
+ FT_Vector kerning;
+
+} Z1_Kern_Pair;
+
+
+typedef struct Z1_AFM_
+{
+ FT_Int num_pairs;
+ Z1_Kern_Pair* kern_pairs;
+
+} Z1_AFM;
+
+
+LOCAL_DEF
+FT_Error Z1_Read_AFM( FT_Face face,
+ FT_Stream stream );
+
+LOCAL_DEF
+void Z1_Done_AFM( FT_Memory memory,
+ Z1_AFM* afm );
+
+LOCAL_DEF
+void Z1_Get_Kerning( Z1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+#endif /* T1AFM_H */
--- /dev/null
+++ b/src/type1z/z1driver.c
@@ -1,0 +1,300 @@
+/*******************************************************************
+ *
+ * t1driver.c
+ *
+ * High-level Type1 driver interface for FreeType 2.0
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <z1driver.h>
+#include <z1gload.h>
+#include <z1load.h>
+#include <z1afm.h>
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1driver
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Interface */
+ /* */
+ /* <Description> */
+ /* Each driver can provide one or more extensions to the base */
+ /* FreeType API. These can be used to access format specific */
+ /* features (e.g., all TrueType/OpenType resources share a common */
+ /* file structure and common tables which can be accessed through the */
+ /* `sfnt' interface), or more simply generic ones (e.g., the */
+ /* `postscript names' interface which can be used to retrieve the */
+ /* PostScript name of a given glyph index). */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to a driver object. */
+ /* */
+ /* <Input> */
+ /* interface :: A string designing the interface. Examples are */
+ /* `sfnt', `post_names', `charmaps', etc. */
+ /* */
+ /* <Return> */
+ /* A typeless pointer to the extension's interface (normally a table */
+ /* of function pointers). Returns NULL if the requested extension */
+ /* isn't available (i.e., wasn't compiled in the driver at build */
+ /* time). */
+ /* */
+ static
+ FT_Module_Interface Get_Interface( FT_Driver driver,
+ const FT_String* interface )
+ {
+ UNUSED(driver);
+ UNUSED(interface);
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+ return (FT_Module_Interface)Z1_Get_Multi_Master;
+
+ if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+ return (FT_Module_Interface)Z1_Set_MM_Design;
+
+ if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+ return (FT_Module_Interface)Z1_Set_MM_Blend;
+#endif
+ return 0;
+ }
+
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+ /*************************************************************************/
+ /* */
+ /* <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
+ FT_Error Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ Z1_AFM* afm;
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ afm = (Z1_AFM*)face->afm_data;
+ if (afm)
+ Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+ return T1_Err_Ok;
+ }
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* <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
+ FT_UInt Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
+ {
+ T1_Face face;
+ FT_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,
+ (FT_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;
+ }
+
+
+ const FT_Driver_Class t1z_driver_class =
+ {
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1z",
+ 0x10000,
+ 0x20000,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor) Z1_Init_Driver,
+ (FT_Module_Destructor) Z1_Done_Driver,
+ (FT_Module_Requester) Get_Interface,
+ },
+
+ sizeof( T1_FaceRec ),
+ sizeof( Z1_SizeRec ),
+ sizeof( Z1_GlyphSlotRec ),
+
+ (FTDriver_initFace) Z1_Init_Face,
+ (FTDriver_doneFace) Z1_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes) 0,
+ (FTDriver_loadGlyph) Z1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef Z1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+#else
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) Z1_Read_AFM,
+#endif
+ (FTDriver_getAdvances) 0
+
+ };
+
+
+ /******************************************************************/
+ /* */
+ /* <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(const FT_Driver_Class*) getDriverClass( void )
+ {
+ return &t1z_driver_class;
+ }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
--- /dev/null
+++ b/src/type1z/z1driver.h
@@ -1,0 +1,26 @@
+/*******************************************************************
+ *
+ * t1driver.h
+ *
+ * High-level Type1 driver interface for FreeType 2.0
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1DRIVER_H
+#define T1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+ FT_EXPORT_VAR(const FT_Driver_Class) t1z_driver_class;
+
+#endif /* T1DRIVER_H */
+
--- /dev/null
+++ b/src/type1z/z1gload.c
@@ -1,0 +1,1382 @@
+/*******************************************************************
+ *
+ * t1gload.c 1.0
+ *
+ * Type1 Glyph Loader.
+ *
+ * Copyright 1996-1999 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <z1gload.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1gload
+
+ typedef enum Z1_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 */
+
+ } Z1_Operator;
+
+ static const FT_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 */
+ };
+
+
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRINGS PARSING *********/
+ /********** *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+
+/*********************************************************************
+ *
+ * <Function>
+ * Z1_Init_Builder
+ *
+ * <Description>
+ * Initialise a given glyph builder.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ * face :: current face object
+ * size :: current size object
+ * glyph :: current glyph object
+ *
+ *********************************************************************/
+
+ LOCAL_FUNC
+ void Z1_Init_Builder( Z1_Builder* builder,
+ T1_Face face,
+ Z1_Size size,
+ Z1_GlyphSlot glyph )
+ {
+ builder->path_begun = 0;
+ builder->load_points = 1;
+
+ builder->face = face;
+ builder->glyph = glyph;
+ builder->memory = face->root.memory;
+
+ if (glyph)
+ {
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+ builder->loader = loader;
+ builder->current = &loader->current.outline;
+ builder->base = &loader->base.outline;
+
+ FT_GlyphLoader_Rewind(loader);
+ }
+
+ if (size)
+ {
+ builder->scale_x = size->root.metrics.x_scale;
+ builder->scale_y = size->root.metrics.y_scale;
+ }
+
+ builder->pos_x = 0;
+ builder->pos_y = 0;
+
+ builder->left_bearing.x = 0;
+ builder->left_bearing.y = 0;
+ builder->advance.x = 0;
+ builder->advance.y = 0;
+ }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ * Z1_Done_Builder
+ *
+ * <Description>
+ * Finalise a given glyph builder. Its content can still be
+ * used after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ *
+ *********************************************************************/
+
+ LOCAL_FUNC
+ void Z1_Done_Builder( Z1_Builder* builder )
+ {
+ Z1_GlyphSlot glyph = builder->glyph;
+
+ if (glyph)
+ glyph->root.outline = *builder->base;
+ }
+
+
+
+/*********************************************************************
+ *
+ * <Function>
+ * Z1_Init_Decoder
+ *
+ * <Description>
+ * Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ * decoder :: Type 1 decoder to initialise
+ * funcs :: hinter functions interface
+ *
+ *********************************************************************/
+
+ LOCAL_FUNC
+ void Z1_Init_Decoder( Z1_Decoder* decoder )
+ {
+ decoder->top = 0;
+ decoder->zone = 0;
+ decoder->flex_state = 0;
+ decoder->num_flex_vectors = 0;
+ decoder->blend = 0;
+
+ /* Clear loader */
+ MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
+ }
+
+
+ /* check that there is enough room for "count" more points */
+ static
+ FT_Error check_points( Z1_Builder* builder,
+ FT_Int count )
+ {
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
+ }
+
+
+ /* add a new point, do not check room */
+ static
+ void add_point( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y,
+ FT_Byte flag )
+ {
+ FT_Outline* outline = builder->current;
+
+ if (builder->load_points)
+ {
+ FT_Vector* point = outline->points + outline->n_points;
+ FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
+
+ point->x = x;
+ point->y = y;
+ *control = ( flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic );
+
+ builder->last = *point;
+ }
+
+ outline->n_points++;
+ }
+
+
+ /* check room for a new on-curve point, then add it */
+ static
+ FT_Error add_point1( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ FT_Error error;
+
+ error = check_points(builder,1);
+ if (!error)
+ add_point( builder, x, y, 1 );
+
+ return error;
+ }
+
+
+ /* check room for a new contour, then add it */
+ static
+ FT_Error add_contour( Z1_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+ FT_Error error;
+
+ if (!builder->load_points)
+ {
+ outline->n_contours++;
+ return FT_Err_Ok;
+ }
+
+ /* realloc contours array if necessary */
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if (!error)
+ {
+ if (outline->n_contours > 0)
+ outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
+
+ outline->n_contours++;
+ }
+ return error;
+ }
+
+ /* if a path was begun, add its first on-curve point */
+ static
+ FT_Error start_point( Z1_Builder* builder,
+ FT_Pos x,
+ FT_Pos y )
+ {
+ /* test wether we're building a new contour */
+ if (!builder->path_begun)
+ {
+ FT_Error error;
+
+ builder->path_begun = 1;
+ error = add_contour( builder );
+ if (error) return error;
+ }
+ return add_point1( builder, x, y );
+ }
+
+
+ /* close the current contour */
+ static
+ void close_contour( Z1_Builder* builder )
+ {
+ FT_Outline* outline = builder->current;
+
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours-1] = outline->n_points-1;
+ }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ * lookup_glyph_by_stdcharcode
+ *
+ * <Description>
+ * Lookup a given glyph by its StandardEncoding charcode. Used
+ * to implement the SEAC Type 1 operator.
+ *
+ * <Input>
+ * face :: current face object
+ * charcode :: charcode to look for
+ *
+ * <Return>
+ * glyph index in font face. Returns -1 if the corresponding
+ * glyph wasn't found.
+ *
+ *********************************************************************/
+
+ static
+ FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
+ FT_Int charcode )
+ {
+ FT_Int n;
+ const FT_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 = psnames->adobe_std_strings(
+ psnames->adobe_std_encoding[charcode]);
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ FT_String* name = (FT_String*)face->type1.glyph_names[n];
+
+ if ( name && strcmp(name,glyph_name) == 0 )
+ return n;
+ }
+
+ return -1;
+ }
+
+
+
+/*********************************************************************
+ *
+ * <Function>
+ * t1operator_seac
+ *
+ * <Description>
+ * Implements the "seac" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * asb :: accent's side bearing
+ * adx :: horizontal position of accent
+ * ady :: vertical position of accent
+ * bchar :: base character's StandardEncoding charcode
+ * achar :: accent character's StandardEncoding charcode
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
+
+ static
+ FT_Error t1operator_seac( Z1_Decoder* decoder,
+ FT_Pos asb,
+ FT_Pos adx,
+ FT_Pos ady,
+ FT_Int bchar,
+ FT_Int achar )
+ {
+ FT_Error error;
+ FT_Int bchar_index, achar_index, n_base_points;
+ FT_Outline* cur = decoder->builder.current;
+ FT_Outline* base = decoder->builder.base;
+ FT_Vector left_bearing, advance;
+ T1_Face face = decoder->builder.face;
+ T1_Font* type1 = &face->type1;
+
+ bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
+ achar_index = lookup_glyph_by_stdcharcode( face, achar );
+
+ if ( bchar_index < 0 || achar_index < 0 )
+ {
+ FT_ERROR(( "t1operator_seac: invalid seac character code arguments\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
+ if ( decoder->builder.no_recurse )
+ {
+
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
+
+ /* reallocate subglyph array if necessary */
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if (error) goto Exit;
+
+ subg = loader->current.subglyphs;
+
+ /* subglyph 0 = base character */
+ subg->index = bchar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+ FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+ subg->arg1 = 0;
+ subg->arg2 = 0;
+ subg++;
+
+ /* subglyph 1 = accent character */
+ subg->index = achar_index;
+ subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+ subg->arg1 = adx - asb;
+ subg->arg2 = ady;
+
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs = 2;
+ glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
+ }
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = Z1_Parse_CharStrings( decoder,
+ type1->charstrings [bchar_index],
+ type1->charstrings_len[bchar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error ) goto Exit;
+
+ n_base_points = cur->n_points;
+
+ {
+ /* save the left bearing and width of the base character */
+ /* as they will be erased by the next load. */
+
+ left_bearing = decoder->builder.left_bearing;
+ advance = decoder->builder.advance;
+
+ decoder->builder.left_bearing.x = 0;
+ decoder->builder.left_bearing.y = 0;
+
+ /* Now load `achar' on top of */
+ /* the base outline */
+ error = Z1_Parse_CharStrings( decoder,
+ type1->charstrings [achar_index],
+ type1->charstrings_len[achar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error ) return error;
+
+ /* restore the left side bearing and */
+ /* advance width of the base character */
+
+ decoder->builder.left_bearing = left_bearing;
+ decoder->builder.advance = advance;
+
+ /* Finally, move the accent */
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
+ }
+ Exit:
+ return error;
+ }
+
+
+/*********************************************************************
+ *
+ * <Function>
+ * Z1_Parse_CharStrings
+ *
+ * <Description>
+ * Parses a given Type 1 charstrings program
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * charstring_base :: base of the charstring stream
+ * charstring_len :: length in bytes of the charstring stream
+ * num_subrs :: number of sub-routines
+ * subrs_base :: array of sub-routines addresses
+ * subrs_len :: array of sub-routines lengths
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
+
+#define USE_ARGS(n) top -= n; if (top < decoder->stack) goto Stack_Underflow
+
+ LOCAL_FUNC
+ FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len )
+ {
+ FT_Error error;
+ Z1_Decoder_Zone* zone;
+ FT_Byte* ip;
+ FT_Byte* limit;
+ Z1_Builder* builder = &decoder->builder;
+ FT_Outline* outline;
+ FT_Pos x, y;
+
+ /* First of all, initialise the decoder */
+ decoder->top = decoder->stack;
+ decoder->zone = decoder->zones;
+ zone = decoder->zones;
+
+ builder->path_begun = 0;
+
+ zone->base = charstring_base;
+ limit = zone->limit = charstring_base + charstring_len;
+ ip = zone->cursor = zone->base;
+
+ error = T1_Err_Ok;
+ outline = builder->current;
+
+ x = builder->pos_x;
+ y = builder->pos_y;
+
+ /* now, execute loop */
+ while ( ip < limit )
+ {
+ FT_Int* top = decoder->top;
+ Z1_Operator op = op_none;
+ FT_Long value = 0;
+
+ /********************************************************************/
+ /* */
+ /* Decode operator or operand */
+ /* */
+ /* */
+
+ /* First of all, decompress operator or value */
+ switch (*ip++)
+ {
+ 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:
+ {
+ 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 ------------------------ */
+ {
+ FT_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,
+ (FT_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;;
+ }
+
+ case 12:
+ case 13:
+ {
+ /* counter control hints, clear stack */
+ top = decoder->stack;
+ break;
+ }
+
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18: /* multiple masters */
+ {
+ T1_Blend* blend = decoder->blend;
+ FT_UInt num_points, nn, mm;
+ FT_Int* delta;
+ FT_Int* values;
+
+ if (!blend)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: unexpected multiple masters operator !!\n" ));
+ goto Syntax_Error;
+ }
+
+ num_points = top[1] - 13 + (top[1] == 18);
+ if (top[0] != (FT_Int)(num_points*blend->num_designs))
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: incorrect number of mm arguments\n" ));
+ goto Syntax_Error;
+ }
+
+ top -= blend->num_designs*num_points;
+ if (top < decoder->stack)
+ goto Stack_Underflow;
+
+ /* we want to compute: */
+ /* */
+ /* a0*w0 + a1*w1 + ... + ak*wk */
+ /* */
+ /* but we only have the a0, a1-a0, a2-a0, .. ak-a0 */
+ /* however, given that w0 + w1 + ... + wk == 1, we can */
+ /* rewrite it easily as: */
+ /* */
+ /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
+ /* */
+ /* where k == num_designs-1 */
+ /* */
+ /* I guess that's why it's written in this "compact" */
+ /* form.. */
+ /* */
+ /* */
+ delta = top + num_points;
+ values = top;
+ for ( nn = 0; nn < num_points; nn++ )
+ {
+ FT_Int x = values[0];
+ for ( mm = 1; mm < blend->num_designs; mm++ )
+ x += FT_MulFix( *delta++, blend->weight_vector[mm] );
+
+ *values++ = x;
+ }
+ /* note that "top" will be incremented later by calls to "pop" */
+ 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 */
+ {
+ FT_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 */
+ FT_GlyphLoader_Add( builder->loader );
+
+ /* 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 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;
+
+ 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;
+
+ x += top[0];
+ y += top[1];
+ Add_Line:
+ if (add_point1( builder, x, y )) goto Memory_Error;
+ break;
+ }
+
+
+ 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;
+
+ x += top[0];
+ y += top[1];
+ add_point( builder, x, y, 0 );
+
+ x += top[2];
+ y += top[3];
+ add_point( builder, x, y, 0 );
+
+ x += top[4];
+ y += top[5];
+ add_point( builder, x, y, 1 );
+ break;
+ }
+
+
+ case op_vhcurveto: /**********************************************/
+ {
+ 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;
+ }
+
+
+ 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];
+ ++top;
+ }
+ else
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : division by 0\n" ));
+ goto Syntax_Error;
+ }
+ break;
+ }
+
+
+ case op_callsubr: /***********************************************/
+ {
+ FT_Int index;
+
+ FT_TRACE4(( " callsubr" ));
+ index = top[0];
+ if ( index < 0 || index >= num_subrs )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = subrs_base[index];
+ zone->limit = zone->base + subrs_len[index];
+ zone->cursor = zone->base;
+
+ if (!zone->base)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
+ break;
+ }
+
+
+ case op_pop: /****************************************************/
+ {
+ FT_TRACE4(( " pop" ));
+ /* theorically, the arguments are already on the stack */
+ top++;
+ break;
+ }
+
+
+ case op_return: /************************************************/
+ {
+ FT_TRACE4(( " return" ));
+ if ( zone <= decoder->zones )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
+ goto Syntax_Error;
+ }
+
+ zone--;
+ ip = zone->cursor;
+ limit = zone->limit;
+ decoder->zone = zone;
+ break;
+ }
+
+ case op_dotsection: /*********************************************/
+ {
+ FT_TRACE4(( " dotsection" ));
+ break;
+ }
+
+ case op_hstem: /**************************************************/
+ {
+ FT_TRACE4(( " hstem" ));
+ break;
+ }
+
+ case op_hstem3: /*************************************************/
+ {
+ FT_TRACE4(( " hstem3" ));
+ break;
+ }
+
+ case op_vstem: /**************************************************/
+ {
+ FT_TRACE4(( " vstem" ));
+ break;
+ }
+
+ case op_vstem3: /*************************************************/
+ {
+ FT_TRACE4(( " vstem3" ));
+ break;
+ }
+
+ case op_setcurrentpoint: /*****************************************/
+ {
+ FT_TRACE4(( " setcurrentpoint" ));
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
+ goto Syntax_Error;
+ }
+
+ default:
+ FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
+ goto Syntax_Error;
+ }
+
+ decoder->top = top;
+
+ } /* general operator processing */
+
+
+ } /* while ip < limit */
+ FT_TRACE4(( "..end..\n\n" ));
+ return error;
+
+ Syntax_Error:
+ return T1_Err_Syntax_Error;
+
+ Stack_Underflow:
+ return T1_Err_Stack_Underflow;
+
+ Memory_Error:
+ return builder->error;
+ }
+
+
+
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly process each glyph charstring to *********/
+ /********** extract the value from either a "sbw" or "seac" *********/
+ /********** operator. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+
+ LOCAL_FUNC
+ FT_Error Z1_Compute_Max_Advance( T1_Face face,
+ FT_Int *max_advance )
+ {
+ FT_Error error;
+ Z1_Decoder decoder;
+ FT_Int glyph_index;
+ T1_Font* type1 = &face->type1;
+
+ *max_advance = 0;
+
+ /* Initialise load decoder */
+ Z1_Init_Decoder( &decoder );
+ Z1_Init_Builder( &decoder.builder, face, 0, 0 );
+
+ decoder.blend = face->blend;
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ /* For each glyph, parse the glyph charstring and extract */
+ /* the advance width.. */
+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = Z1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ /* ignore the error if one occured - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+ return T1_Err_Ok;
+ }
+
+
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
+ Z1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ Z1_Decoder decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font* type1 = &face->type1;
+
+ if (load_flags & FT_LOAD_NO_RECURSE)
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ {
+ Z1_Init_Decoder( &decoder );
+ Z1_Init_Builder( &decoder.builder, face, size, glyph );
+
+ decoder.blend = ((T1_Face)glyph->root.face)->blend;
+ decoder.builder.no_recurse = (FT_Bool)!!(load_flags & FT_LOAD_NO_RECURSE);
+
+ /* now load the unscaled outline */
+ error = Z1_Parse_CharStrings( &decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+
+ /* save new glyph tables */
+ Z1_Done_Builder( &decoder.builder );
+ }
+
+ /* Now, set the metrics.. - this is rather simple, as : */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax.. */
+ if (!error)
+ {
+ /* for composite glyphs, return only the left side bearing and the */
+ /* advance width.. */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ glyph->root.outline.flags &= ft_outline_owner;
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+ /*
+ glyph->root.outline.second_pass = TRUE;
+ glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+ glyph->root.outline.dropout_mode = 2;
+ */
+
+ if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
+ }
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline, &face->type1.font_matrix );
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if (hinting)
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax+63 ) & -64;
+ cbox.yMax = ( cbox.yMax+63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+ }
+ }
+ return error;
+ }
+
--- /dev/null
+++ b/src/type1z/z1gload.h
@@ -1,0 +1,188 @@
+/*******************************************************************
+ *
+ * t1gload.h 1.0
+ *
+ * Type1 Glyph Loader.
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ *
+ * The Type 1 glyph loader uses three distinct objects to build
+ * scaled and hinted outlines from a charstrings program. These are :
+ *
+ * - a glyph builder, Z1_Builder, used to store the built outline
+ *
+ * - a glyph hinter, Z1_Hinter, used to record and apply the stem
+ * hints
+ *
+ * - a charstrings interpreter, Z1_Decoder, used to parse the
+ * Type 1 charstrings stream, manage a stack and call the builder
+ * and/or hinter depending on the opcodes.
+ *
+ * Ideally, a Type 2 glyph loader would only need to have its own
+ * T2_Decoder object (assuming the hinter is able to manage all
+ * kinds of hints).
+ *
+ ******************************************************************/
+
+#ifndef T1GLOAD_H
+#define T1GLOAD_H
+
+#include <z1objs.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+/*************************************************************************/
+/* */
+/* <Structure> Z1_Builder */
+/* */
+/* <Description> */
+/* a structure used during glyph loading to store its outline. */
+/* */
+/* <Fields> */
+/* system :: current system object */
+/* face :: current face object */
+/* glyph :: current glyph slot */
+/* */
+/* current :: current glyph outline */
+/* base :: base glyph outline */
+/* */
+/* max_points :: maximum points in builder outline */
+/* max_contours :: maximum contours in builder outline */
+/* */
+/* last :: last point position */
+/* */
+/* scale_x :: horizontal scale ( FUnits to sub-pixels ) */
+/* scale_y :: vertical scale ( FUnits to sub-pixels ) */
+/* pos_x :: horizontal translation (composite glyphs) */
+/* pos_y :: vertical translation (composite glyph) */
+/* */
+/* left_bearing :: left side bearing point */
+/* advance :: horizontal advance vector */
+/* */
+/* path_begun :: flag, indicates that a new path has begun */
+/* load_points :: flag, if not set, no points are loaded */
+/* */
+/* error :: an error code that is only used to report */
+/* memory allocation problems.. */
+/* */
+/* metrics_only :: a boolean indicating that we only want to */
+/* compute the metrics of a given glyph, not load */
+/* all of its points.. */
+/* */
+
+ typedef struct Z1_Builder_
+ {
+ FT_Memory memory;
+ T1_Face face;
+ Z1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+
+ FT_Outline* current; /* the current glyph outline */
+ FT_Outline* base; /* the composite glyph outline */
+
+ FT_Vector last;
+
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
+
+ FT_Pos pos_x;
+ FT_Pos pos_y;
+
+ FT_Vector left_bearing;
+ FT_Vector advance;
+
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
+
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
+
+ } Z1_Builder;
+
+
+ /* execution context charstring zone */
+ typedef struct Z1_Decoder_Zone_
+ {
+ FT_Byte* base;
+ FT_Byte* limit;
+ FT_Byte* cursor;
+
+ } Z1_Decoder_Zone;
+
+
+ typedef struct Z1_Decoder_
+ {
+ Z1_Builder builder;
+
+ FT_Int stack[ T1_MAX_CHARSTRINGS_OPERANDS ];
+ FT_Int* top;
+
+ Z1_Decoder_Zone zones[ T1_MAX_SUBRS_CALLS+1 ];
+ Z1_Decoder_Zone* zone;
+
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
+
+ T1_Blend* blend; /* for multiple masters */
+
+ } Z1_Decoder;
+
+
+
+ LOCAL_DEF
+ void Z1_Init_Builder( Z1_Builder* builder,
+ T1_Face face,
+ Z1_Size size,
+ Z1_GlyphSlot glyph );
+
+ LOCAL_DEF
+ void Z1_Done_Builder( Z1_Builder* builder );
+
+
+ LOCAL_DEF
+ void Z1_Init_Decoder( Z1_Decoder* decoder );
+
+
+ /* Compute the maximum advance width of a font through quick parsing */
+ LOCAL_DEF
+ FT_Error Z1_Compute_Max_Advance( T1_Face face,
+ FT_Int *max_advance );
+
+
+ /* This function is exported, because it is used by the T1Dump utility */
+ LOCAL_DEF
+ FT_Error Z1_Parse_CharStrings( Z1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len );
+
+
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
+ Z1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1GLOAD_H */
--- /dev/null
+++ b/src/type1z/z1load.c
@@ -1,0 +1,1473 @@
+/*******************************************************************
+ *
+ * t1load.h 2.0
+ *
+ * Type1 Loader.
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ *
+ * This is the new and improved Type 1 data loader for FreeType 2.
+ * The old loader has several problems: it is slow, complex, difficult
+ * to maintain, and contains incredible hacks to make it accept some
+ * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5%
+ * of the Type 1 fonts on my machine still aren't loaded correctly
+ * by it.
+ *
+ * This version is much simpler, much faster and also easier to
+ * read and maintain by a great order of magnitude. The idea behind
+ * it is to _not_ try to read the Type 1 token stream with a state
+ * machine (i.e. a Postscript-like interpreter) but rather to perform
+ * simple pattern-matching.
+ *
+ * Indeed, nearly all data definitions follow a simple pattern
+ * like :
+ *
+ * ..... /Field <data> ....
+ *
+ * where <data> can be a number, a boolean, a string, or an
+ * array of numbers. There are a few exceptions, namely the
+ * encoding, font name, charstrings and subrs and they are
+ * handled with a special pattern-matching routine.
+ *
+ * All other common cases are handled very simply. The matching
+ * rules are defined in the file "t1tokens.h" through the use
+ * of several macros calls PARSE_XXXX
+ *
+ * This file is included twice here, the first time to generate
+ * parsing callback functions, the second to generate a table
+ * of keywords (with pointers to the associated callback).
+ *
+ * The function "parse_dict" simply scans *linearly* a given
+ * dictionary (either the top-level or private one) and calls
+ * the appropriate callback when it encounters an immediate
+ * keyword.
+ *
+ * This is by far the fastest way one can find to parse and read
+ * all data :-)
+ *
+ * This led to tremendous code size reduction. Note that later,
+ * the glyph loader will also be _greatly_ simplified, and the
+ * automatic hinter will replace the clumsy "t1hinter"..
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+#include <z1load.h>
+#include <stdio.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1load
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SUPPORT *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+ static FT_Error t1_allocate_blend( T1_Face face,
+ FT_UInt num_designs,
+ FT_UInt num_axis )
+ {
+ T1_Blend* blend;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = 0;
+
+ blend = face->blend;
+ if (!blend)
+ {
+ if ( ALLOC( blend, sizeof(*blend) ) )
+ goto Exit;
+
+ face->blend = blend;
+ }
+
+ /* allocate design data if needed */
+ if (num_designs > 0)
+ {
+ if (blend->num_designs == 0)
+ {
+ /* allocate the blend "private" and "font_info" dictionaries */
+ if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
+ ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
+ ALLOC_ARRAY( blend->weight_vector, num_designs*2, FT_Fixed ) )
+ goto Exit;
+
+ blend->default_weight_vector = blend->weight_vector + num_designs;
+
+ blend->font_infos[0] = &face->type1.font_info;
+ blend->privates [0] = &face->type1.private_dict;
+ blend->num_designs = num_designs;
+ }
+ else if (blend->num_designs != num_designs)
+ goto Fail;
+ }
+
+ /* allocate axis data if needed */
+ if (num_axis > 0)
+ {
+ if (blend->num_axis != 0 && blend->num_axis != num_axis)
+ goto Fail;
+
+ blend->num_axis = num_axis;
+ }
+
+ /* allocate the blend design pos table if needed */
+ num_designs = blend->num_designs;
+ num_axis = blend->num_axis;
+ if ( num_designs && num_axis && blend->design_pos[0] == 0)
+ {
+ FT_UInt n;
+
+ if ( ALLOC_ARRAY( blend->design_pos[0], num_designs*num_axis, FT_Fixed ) )
+ goto Exit;
+
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = blend->design_pos[0] + num_axis*n;
+ }
+
+ Exit:
+ return error;
+ Fail:
+ error = -1;
+ goto Exit;
+ }
+
+ LOCAL_FUNC FT_Error Z1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master )
+ {
+ T1_Blend* blend = face->blend;
+ FT_UInt n;
+ FT_Error error;
+
+ error = T1_Err_Invalid_Argument;
+ if (blend)
+ {
+ master->num_axis = blend->num_axis;
+ master->num_designs = blend->num_designs;
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_MM_Axis* axis = master->axis + n;
+ T1_DesignMap* map = blend->design_map + n;
+
+ axis->name = blend->axis_names[n];
+ axis->minimum = map->design_points[0];
+ axis->maximum = map->design_points[map->num_points-1];
+ }
+ error = 0;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC FT_Error Z1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, m;
+
+ error = T1_Err_Invalid_Argument;
+ if (blend && blend->num_axis == num_coords)
+ {
+ /* recompute the weight vector from the blend coordinates */
+ error = 0;
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ FT_Fixed result = 0x10000L; /* 1.0 fixed */
+ for ( m = 0; m < blend->num_axis; m++ )
+ {
+ FT_Fixed factor;
+
+ /* get current blend axis position */
+ factor = coords[m];
+ if (factor < 0) factor = 0;
+ if (factor > 0x10000L) factor = 0x10000L;
+
+ if ((n & (1 << m)) == 0)
+ factor = 0x10000L - factor;
+
+ result = FT_MulFix( result, factor );
+ }
+ blend->weight_vector[n] = result;
+ }
+ error = 0;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC FT_Error Z1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, p;
+
+ error = T1_Err_Invalid_Argument;
+ if (blend && blend->num_axis == num_coords)
+ {
+ /* compute the blend coordinates through the blend design map */
+ FT_Fixed final_blends[ T1_MAX_MM_DESIGNS ];
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_Long design = coords[n];
+ FT_Fixed the_blend;
+ T1_DesignMap* map = blend->design_map + n;
+ FT_Fixed* designs = map->design_points;
+ FT_Fixed* blends = map->blend_points;
+ FT_Int before = -1, after = -1;
+
+ for ( p = 0; p < map->num_points; p++ )
+ {
+ FT_Fixed p_design = designs[p];
+
+ /* exact match ? */
+ if (design == p_design)
+ {
+ the_blend = blends[p];
+ goto Found;
+ }
+
+ if (design < p_design)
+ {
+ after = p;
+ break;
+ }
+
+ before = p;
+ }
+
+ /* now, interpolate if needed */
+ if (before < 0)
+ the_blend = blends[0];
+
+ else if (after < 0)
+ the_blend = blends[map->num_points-1];
+
+ else
+ the_blend = FT_MulDiv( design - designs[before],
+ blends [after] - blends [before],
+ designs[after] - designs[before] );
+ Found:
+ final_blends[n] = the_blend;
+ }
+
+ error = Z1_Set_MM_Blend( face, num_coords, final_blends );
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC void Z1_Done_Blend( T1_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ T1_Blend* blend = face->blend;
+
+ if (blend)
+ {
+ FT_UInt num_designs = blend->num_designs;
+ FT_UInt num_axis = blend->num_axis;
+ FT_UInt n;
+
+ /* release design pos table */
+ FREE( blend->design_pos[0] );
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = 0;
+
+ /* release blend "private" and "font info" dictionaries */
+ FREE( blend->privates[1] );
+ FREE( blend->font_infos[1] );
+ for ( n = 0; n < num_designs; n++ )
+ {
+ blend->privates [n] = 0;
+ blend->font_infos[n] = 0;
+ }
+
+ /* release weight vectors */
+ FREE( blend->weight_vector );
+ blend->default_weight_vector = 0;
+
+ /* release axis names */
+ for ( n = 0; n < num_axis; n++ )
+ FREE( blend->axis_names[n] );
+
+ /* release design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* dmap = blend->design_map + n;
+ FREE( dmap->design_points );
+ dmap->num_points = 0;
+ }
+
+ FREE( face->blend );
+ }
+ }
+
+
+
+ static void parse_blend_axis_types( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Error error = 0;
+ T1_Blend* blend;
+ FT_Memory memory;
+
+ /* take an array of objects */
+ Z1_ToTokenArray( &loader->parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+ if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
+ {
+ FT_ERROR(( "T1.parse_blend_axis_types: incorrect number of axis: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate blend if necessary */
+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+ if (error) goto Exit;
+
+ blend = face->blend;
+ memory = face->root.memory;
+
+ /* each token is an immediate containing the name of the axis */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ Z1_Token_Rec* token = axis_tokens + n;
+ FT_Byte* name;
+ FT_Int len;
+
+ /* skip first slash, if any */
+ if (token->start[0] == '/')
+ token->start++;
+
+ len = token->limit - token->start;
+ if (len <= 0)
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( ALLOC( blend->axis_names[n], len+1 ) )
+ goto Exit;
+
+ name = (FT_Byte*)blend->axis_names[n];
+ MEM_Copy( name, token->start, len );
+ name[len] = 0;
+ }
+
+ Exit:
+ loader->parser.error = error;
+ }
+
+
+ static void parse_blend_design_positions( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Token_Rec design_tokens[ T1_MAX_MM_DESIGNS ];
+ FT_Int num_designs;
+ FT_Int num_axis;
+ Z1_Parser* parser = &loader->parser;
+
+ FT_Error error = 0;
+ T1_Blend* blend;
+
+ /* get the array of design tokens - compute number of designs */
+ Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+ if (num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS)
+ {
+ FT_ERROR(( "T1.design positions: incorrect number of designs: %d\n",
+ num_designs ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ FT_UInt n;
+
+ blend = face->blend;
+ num_axis = 0; /* make compiler happy */
+ for ( n = 0; n < (FT_UInt)num_designs; n++ )
+ {
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_DESIGNS ];
+ Z1_Token_Rec* token;
+ FT_Int axis, n_axis;
+
+ /* read axis/coordinates tokens */
+ token = design_tokens + n;
+ parser->cursor = token->start - 1;
+ parser->limit = token->limit + 1;
+ Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+ if (n == 0)
+ {
+ num_axis = n_axis;
+ error = t1_allocate_blend( face, num_designs, num_axis );
+ if (error) goto Exit;
+ blend = face->blend;
+ }
+ else if (n_axis != num_axis)
+ {
+ FT_ERROR(( "T1.design_positions: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now, read each axis token into the design position */
+ for (axis = 0; axis < n_axis; axis++ )
+ {
+ Z1_Token_Rec* token2 = axis_tokens + axis;
+ parser->cursor = token2->start;
+ parser->limit = token2->limit;
+ blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
+ }
+ }
+
+ loader->parser.cursor = old_cursor;
+ loader->parser.limit = old_limit;
+ }
+
+ Exit:
+ loader->parser.error = error;
+ }
+
+ static void parse_blend_design_map( T1_Face face, Z1_Loader* loader )
+ {
+ FT_Error error = 0;
+ Z1_Parser* parser = &loader->parser;
+ T1_Blend* blend;
+ Z1_Token_Rec axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ FT_Memory memory = face->root.memory;
+
+ Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+ if (num_axis <= 0 || num_axis > T1_MAX_MM_AXIS)
+ {
+ FT_ERROR(( "T1.design map: incorrect number of axis: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ error = t1_allocate_blend( face, 0, num_axis );
+ if (error) goto Exit;
+ blend = face->blend;
+
+ /* now, read each axis design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* map = blend->design_map + n;
+ Z1_Token_Rec* token;
+ FT_Int p, num_points;
+
+ token = axis_tokens + n;
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+
+ /* count the number of map points */
+ {
+ FT_Byte* p = token->start;
+ FT_Byte* limit = token->limit;
+
+ num_points = 0;
+ for ( ; p < limit; p++ )
+ if (p[0] == '[')
+ num_points++;
+ }
+ if (num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS)
+ {
+ FT_ERROR(( "T1.design map: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate design map data */
+ if ( ALLOC_ARRAY( map->design_points, num_points*2, FT_Fixed ) )
+ goto Exit;
+ map->blend_points = map->design_points + num_points;
+ map->num_points = (FT_Byte)num_points;
+
+ for ( p = 0; p < num_points; p++ )
+ {
+ map->design_points[p] = Z1_ToInt( parser );
+ map->blend_points [p] = Z1_ToFixed( parser, 0 );
+ }
+ }
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ Exit:
+ parser->error = error;
+ }
+
+ static void parse_weight_vector( T1_Face face, Z1_Loader* loader )
+ {
+ FT_Error error = 0;
+ Z1_Parser* parser = &loader->parser;
+ T1_Blend* blend = face->blend;
+ Z1_Token_Rec master;
+ FT_UInt n;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+
+ if (!blend || blend->num_designs == 0)
+ {
+ FT_ERROR(( "t1.weight_vector: too early !!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ Z1_ToToken( parser, &master );
+ if (master.type != t1_token_array)
+ {
+ FT_ERROR(( "t1.weight_vector: incorrect format !!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ blend->default_weight_vector[n] =
+ blend->weight_vector[n] = Z1_ToFixed( parser, 0 );
+ }
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ Exit:
+ parser->error = error;
+ }
+
+ /* the keyword /shareddict appears in some multiple master fonts with a lot */
+ /* of Postscript garbage behind it (that's completely out of spec !!), we */
+ /* detect it and terminate the parsing */
+ static void parse_shared_dict( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+ UNUSED(face);
+
+ parser->cursor = parser->limit;
+ parser->error = 0;
+ }
+#endif
+
+ /***************************************************************************/
+ /***************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /***************************************************************************/
+ /***************************************************************************/
+
+ /*********************************************************************
+ *
+ * First of all, define the token field static variables. This is
+ * a set of Z1_Field_Rec variables used later..
+ *
+ *********************************************************************/
+
+#define Z1_NEW_STRING( _name, _field ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_STRING( T1TYPE, _field );
+
+#define Z1_NEW_BOOL( _name, _field ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_BOOL( T1TYPE, _field );
+
+#define Z1_NEW_NUM( _name, _field ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM( T1TYPE, _field );
+
+#define Z1_NEW_FIXED( _name, _field ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED( T1TYPE, _field, _power );
+
+#define Z1_NEW_NUM_TABLE( _name, _field, _max, _count ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_FIXED_TABLE( _name, _field, _max, _count ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED_ARRAY( T1TYPE, _field, _count, _max );
+
+#define Z1_NEW_NUM_TABLE2( _name, _field, _max ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_NUM_ARRAY2( T1TYPE, _field, _max );
+
+#define Z1_NEW_FIXED_TABLE2( _name, _field, _max ) \
+ static const Z1_Field_Rec t1_field_ ## _field = Z1_FIELD_FIXED_ARRAY2( T1TYPE, _field, _max );
+
+
+#define Z1_FONTINFO_STRING(n,f) Z1_NEW_STRING(n,f)
+#define Z1_FONTINFO_NUM(n,f) Z1_NEW_NUM(n,f)
+#define Z1_FONTINFO_BOOL(n,f) Z1_NEW_BOOL(n,f)
+#define Z1_PRIVATE_NUM(n,f) Z1_NEW_NUM(n,f)
+#define Z1_PRIVATE_FIXED(n,f) Z1_NEW_FIXED(n,f)
+#define Z1_PRIVATE_NUM_TABLE(n,f,m,c) Z1_NEW_NUM_TABLE(n,f,m,c)
+#define Z1_PRIVATE_NUM_TABLE2(n,f,m) Z1_NEW_NUM_TABLE2(n,f,m)
+#define Z1_TOPDICT_NUM(n,f) Z1_NEW_NUM(n,f)
+#define Z1_TOPDICT_NUM_FIXED2(n,f,m) Z1_NEW_FIXED_TABLE2(n,f,m)
+
+/* including this file defines all field variables */
+#include <z1tokens.h>
+
+ /*********************************************************************
+ *
+ * Second, define the keyword variables. This is a set of Z1_KeyWord
+ * structures used to model the way each keyword is "loaded"..
+ *
+ *********************************************************************/
+
+ typedef void (*Z1_Parse_Func)( T1_Face face, Z1_Loader* loader );
+
+ typedef enum Z1_KeyWord_Type_
+ {
+ t1_keyword_callback = 0,
+ t1_keyword_field,
+ t1_keyword_field_table
+
+ } Z1_KeyWord_Type;
+
+ typedef enum Z1_KeyWord_Location_
+ {
+ t1_keyword_type1 = 0,
+ t1_keyword_font_info,
+ t1_keyword_private
+
+ } Z1_KeyWord_Location;
+
+ typedef struct Z1_KeyWord_
+ {
+ const char* name;
+ Z1_KeyWord_Type type;
+ Z1_KeyWord_Location location;
+ Z1_Parse_Func parsing;
+ const Z1_Field_Rec* field;
+
+ } Z1_KeyWord;
+
+
+#define Z1_KEYWORD_CALLBACK( name, callback ) \
+ { name, t1_keyword_callback, t1_keyword_type1, callback, 0 }
+
+#define Z1_KEYWORD_TYPE1( name, f ) \
+ { name, t1_keyword_field, t1_keyword_type1, 0, &t1_field_ ## f }
+
+#define Z1_KEYWORD_FONTINFO( name, f ) \
+ { name, t1_keyword_field, t1_keyword_font_info, 0, &t1_field_ ## f }
+
+#define Z1_KEYWORD_PRIVATE( name, f ) \
+ { name, t1_keyword_field, t1_keyword_private, 0, &t1_field_ ## f }
+
+#define Z1_KEYWORD_FONTINFO_TABLE( name, f ) \
+ { name, t1_keyword_field_table, t1_keyword_font_info, 0, &t1_field_ ## f }
+
+#define Z1_KEYWORD_PRIVATE_TABLE( name, f ) \
+ { name, t1_keyword_field_table, t1_keyword_private, 0, &t1_field_ ## f }
+
+#undef Z1_FONTINFO_STRING
+#undef Z1_FONTINFO_NUM
+#undef Z1_FONTINFO_BOOL
+#undef Z1_PRIVATE_NUM
+#undef Z1_PRIVATE_FIXED
+#undef Z1_PRIVATE_NUM_TABLE
+#undef Z1_PRIVATE_NUM_TABLE2
+#undef Z1_TOPDICT_NUM
+#undef Z1_TOPDICT_NUM_FIXED2
+
+#define Z1_FONTINFO_STRING(n,f) Z1_KEYWORD_FONTINFO(n,f),
+#define Z1_FONTINFO_NUM(n,f) Z1_KEYWORD_FONTINFO(n,f),
+#define Z1_FONTINFO_BOOL(n,f) Z1_KEYWORD_FONTINFO(n,f),
+#define Z1_PRIVATE_NUM(n,f) Z1_KEYWORD_PRIVATE(n,f),
+#define Z1_PRIVATE_FIXED(n,f) Z1_KEYWORD_PRIVATE(n,f),
+#define Z1_PRIVATE_NUM_TABLE(n,f,m,c) Z1_KEYWORD_PRIVATE_TABLE(n,f),
+#define Z1_PRIVATE_NUM_TABLE2(n,f,m) Z1_KEYWORD_PRIVATE_TABLE(n,f),
+#define Z1_TOPDICT_NUM(n,f) Z1_KEYWORD_TYPE1(n,f),
+#define Z1_TOPDICT_NUM_FIXED2(n,f,m) Z1_KEYWORD_TYPE1(n,f),
+
+
+ static FT_Error t1_load_keyword( T1_Face face,
+ Z1_Loader* loader,
+ Z1_KeyWord* keyword )
+ {
+ FT_Error error;
+ void* dummy_object;
+ void** objects;
+ FT_UInt max_objects;
+ T1_Blend* blend = face->blend;
+
+ /* if the keyword has a dedicated callback, call it */
+ if (keyword->type == t1_keyword_callback)
+ {
+ keyword->parsing( face, loader );
+ error = loader->parser.error;
+ goto Exit;
+ }
+
+ /* now, the keyword is either a simple field, or a table of fields */
+ /* we are now going to take care of it.. */
+ switch (keyword->location)
+ {
+ case t1_keyword_font_info:
+ {
+ dummy_object = &face->type1.font_info;
+ objects = &dummy_object;
+ max_objects = 0;
+ if (blend)
+ {
+ objects = (void**)blend->font_infos;
+ max_objects = blend->num_designs;
+ }
+ }
+ break;
+
+ case t1_keyword_private:
+ {
+ dummy_object = &face->type1.private_dict;
+ objects = &dummy_object;
+ max_objects = 0;
+ if (blend)
+ {
+ objects = (void**)blend->privates;
+ max_objects = blend->num_designs;
+ }
+ }
+ break;
+
+ default:
+ dummy_object = &face->type1;
+ objects = &dummy_object;
+ max_objects = 0;
+ }
+
+ if (keyword->type == t1_keyword_field_table)
+ error = Z1_Load_Field_Table( &loader->parser, keyword->field, objects, max_objects, 0 );
+ else
+ error = Z1_Load_Field( &loader->parser, keyword->field, objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ int is_space( char c )
+ {
+ return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+ }
+
+ static
+ int is_alpha( char c )
+ {
+ return ( (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ (c == '.') ||
+ (c == '_') );
+ }
+
+ static
+ void skip_whitespace( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+
+ while ( cur < parser->limit && is_space(*cur) )
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+ static
+ void skip_blackspace( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+
+ while ( cur < parser->limit && !is_space(*cur) )
+ cur++;
+
+ parser->cursor = cur;
+ }
+
+ static
+ int read_binary_data( Z1_Parser* parser, FT_Int *size, FT_Byte* *base )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit = parser->limit;
+
+ /* the binary data has the following format */
+ /* */
+ /* "size" [white*] RD white ....... ND */
+ /* */
+
+ skip_whitespace(parser);
+ cur = parser->cursor;
+
+ if ( cur < limit && (FT_Byte)(*cur-'0') < 10 )
+ {
+ *size = Z1_ToInt(parser);
+
+ skip_whitespace(parser);
+ skip_blackspace(parser); /* "RD" or "-|" or something else */
+
+ /* there is only one whitespace char after the */
+ /* "RD" or "-|" token */
+ *base = parser->cursor + 1;
+
+ parser->cursor += *size+1;
+ return 1;
+ }
+
+ FT_ERROR(( "type1.read_binary_data: invalid size field\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ return 0;
+ }
+
+
+ /* we will now define the routines used to handle */
+ /* the /Encoding, /Subrs and /CharStrings */
+ /* dictionaries.. */
+
+ static
+ void parse_font_name( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Error error;
+ FT_Memory memory = parser->memory;
+ FT_Int len;
+ FT_Byte* cur;
+ FT_Byte* cur2;
+ FT_Byte* limit;
+
+ skip_whitespace(parser);
+ cur = parser->cursor;
+ limit = parser->limit;
+ if ( cur >= limit-1 || *cur != '/' ) return;
+
+ cur++;
+ cur2 = cur;
+ while (cur2 < limit && is_alpha(*cur2)) cur2++;
+ len = cur2-cur;
+ if (len > 0)
+ {
+ if ( ALLOC( face->type1.font_name, len+1 ) )
+ {
+ parser->error = error;
+ return;
+ }
+
+ MEM_Copy( face->type1.font_name, cur, len );
+ face->type1.font_name[len] = '\0';
+ }
+ parser->cursor = cur2;
+ }
+
+ static
+ void parse_font_bbox( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Short temp[4];
+ FT_BBox* bbox = &face->type1.font_bbox;
+
+ (void)Z1_ToCoordArray( parser, 4, temp );
+ bbox->xMin = temp[0];
+ bbox->yMin = temp[1];
+ bbox->xMax = temp[2];
+ bbox->yMax = temp[3];
+ }
+
+ static
+ void parse_font_matrix( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ FT_Fixed temp[4];
+
+ (void)Z1_ToFixedArray( parser, 4, temp, 3 );
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+ }
+
+
+
+ static
+ void parse_encoding( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+ /* skip whitespace */
+ while (is_space(*cur))
+ {
+ cur++;
+ if (cur >= limit)
+ {
+ FT_ERROR(( "type1.parse_encoding: out of bounds !!\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ return;
+ }
+ }
+
+ /* if we have a number, then the encoding is an array, */
+ /* and we must load it now */
+ if ((FT_Byte)(*cur - '0') < 10)
+ {
+ T1_Encoding* encode = &face->type1.encoding;
+ FT_Int count, n;
+ Z1_Table* char_table = &loader->encoding_table;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+ /* read the number of entries in the encoding, should be 256 */
+ count = Z1_ToInt( parser );
+ if (parser->error) return;
+
+ /* we use a Z1_Table to store our charnames */
+ encode->num_chars = count;
+ if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ||
+ ALLOC_ARRAY( encode->char_name, count, FT_String* ) ||
+ (error = Z1_New_Table( char_table, count, memory )) != 0 )
+ {
+ parser->error = error;
+ return;
+ }
+
+ /* now, we will need to read a record of the form */
+ /* ... charcode /charname ... for each entry in our table */
+ /* */
+ /* we simply look for a number followed by an immediate */
+ /* name. Note that this ignores correctly the sequence */
+ /* that is often seen in type1 fonts : */
+ /* */
+ /* 0 1 255 { 1 index exch /.notdef put } for dup */
+ /* */
+ /* used to clean the encoding array before anything else */
+ /* */
+ /* we stop when we encounter a "def" */
+ /* */
+
+ cur = parser->cursor;
+ limit = parser->limit;
+ n = 0;
+
+ for ( ; cur < limit; )
+ {
+ FT_Byte c;
+
+ c = *cur;
+
+ /* we stop when we encounter a 'def' */
+ if ( c == 'd' && cur+3 < limit )
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ is_space(cur[-1]) &&
+ is_space(cur[3]) )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ break;
+ }
+ }
+
+ /* otherwise, we must find a number before anything else */
+ if ( (FT_Byte)(c-'0') < 10 )
+ {
+ FT_Int charcode;
+
+ parser->cursor = cur;
+ charcode = Z1_ToInt(parser);
+ cur = parser->cursor;
+
+ /* skip whitespace */
+ while (cur < limit && is_space(*cur)) cur++;
+
+ if (cur < limit && *cur == '/')
+ {
+ /* bingo, we have an immediate name - it must be a */
+ /* character name */
+ FT_Byte* cur2 = cur+1;
+ FT_Int len;
+
+ while (cur2 < limit && is_alpha(*cur2)) cur2++;
+ len = cur2-cur-1;
+ parser->error = Z1_Add_Table( char_table, charcode, cur+1, len+1 );
+ char_table->elements[charcode][len] = '\0';
+ if (parser->error) return;
+
+ cur = cur2;
+ }
+ }
+ else
+ cur++;
+ }
+
+ face->type1.encoding_type = t1_encoding_array;
+ parser->cursor = cur;
+ }
+ /* Otherwise, we should have either "StandardEncoding" or */
+ /* "ExpertEncoding" */
+ else
+ {
+ if ( cur+17 < limit &&
+ strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ face->type1.encoding_type = t1_encoding_standard;
+
+ else if ( cur+15 < limit &&
+ strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ face->type1.encoding_type = t1_encoding_expert;
+
+ else
+ {
+ FT_ERROR(( "type1.parse_encoding: invalid token !!\n" ));
+ parser->error = T1_Err_Invalid_File_Format;
+ }
+ }
+ }
+
+
+ static
+ void parse_subrs( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ Z1_Table* table = &loader->subrs;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+ FT_Int n;
+
+ loader->num_subrs = Z1_ToInt( parser );
+ if (parser->error) return;
+
+ /* initialise subrs array */
+ error = Z1_New_Table( table, loader->num_subrs, memory );
+ if (error) goto Fail;
+
+ /* the format is simple : */
+ /* */
+ /* "index" + binary data */
+ /* */
+
+ for ( n = 0; n < loader->num_subrs; n++ )
+ {
+ FT_Int index, size;
+ FT_Byte* base;
+
+ index = Z1_ToInt(parser);
+ if (!read_binary_data(parser,&size,&base)) return;
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded.. */
+ /* */
+ /* thanks to Tom Kacvinsky for pointing this out.. */
+ /* */
+ if (face->type1.private_dict.lenIV >= 0)
+ {
+ Z1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = Z1_Add_Table( table, index, base, size );
+ if (error) goto Fail;
+ }
+ return;
+
+ Fail:
+ parser->error = error;
+ }
+
+
+
+
+ static
+ void parse_charstrings( T1_Face face, Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+ Z1_Table* code_table = &loader->charstrings;
+ Z1_Table* name_table = &loader->glyph_names;
+ FT_Memory memory = parser->memory;
+ FT_Error error;
+
+ FT_Byte* cur;
+ FT_Byte* limit = parser->limit;
+ FT_Int n;
+
+ loader->num_glyphs = Z1_ToInt( parser );
+ if (parser->error) return;
+
+ /* initialise tables */
+ error = Z1_New_Table( code_table, loader->num_glyphs, memory ) ||
+ Z1_New_Table( name_table, loader->num_glyphs, memory );
+ if (error) goto Fail;
+
+ n = 0;
+ for ( ;; )
+ {
+ FT_Int size;
+ FT_Byte* base;
+
+ /* the format is simple : */
+ /* "/glyphname" + binary data */
+ /* */
+ /* note that we stop when we find a "def" */
+ /* */
+ skip_whitespace(parser);
+ cur = parser->cursor;
+ if (cur >= limit) break;
+
+ /* 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
+ {
+ FT_Byte* cur2 = cur+1;
+ FT_Int len;
+
+ while (cur2 < limit && is_alpha(*cur2)) cur2++;
+ len = cur2-cur-1;
+
+ error = Z1_Add_Table( name_table, n, cur+1, len+1 );
+ if (error) goto Fail;
+
+ /* add a trailing zero to the name table */
+ name_table->elements[n][len] = '\0';
+
+ parser->cursor = cur2;
+ if (!read_binary_data(parser,&size,&base)) return;
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded.. */
+ /* */
+ /* thanks to Tom Kacvinsky for pointing this out.. */
+ /* */
+ if (face->type1.private_dict.lenIV >= 0)
+ {
+ Z1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = Z1_Add_Table( code_table, n, base, size );
+ if (error) goto Fail;
+
+ n++;
+ if (n >= loader->num_glyphs)
+ break;
+ }
+ }
+ loader->num_glyphs = n;
+ return;
+
+ Fail:
+ parser->error = error;
+ }
+
+
+
+
+ static
+ const Z1_KeyWord t1_keywords[] =
+ {
+#include <z1tokens.h>
+
+ /* now add the special functions... */
+ Z1_KEYWORD_CALLBACK( "FontName", parse_font_name ),
+ Z1_KEYWORD_CALLBACK( "FontBBox", parse_font_bbox ),
+ Z1_KEYWORD_CALLBACK( "FontMatrix", parse_font_matrix ),
+ Z1_KEYWORD_CALLBACK( "Encoding", parse_encoding ),
+ Z1_KEYWORD_CALLBACK( "Subrs", parse_subrs ),
+ Z1_KEYWORD_CALLBACK( "CharStrings", parse_charstrings ),
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ Z1_KEYWORD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ),
+ Z1_KEYWORD_CALLBACK( "BlendDesignMap", parse_blend_design_map ),
+ Z1_KEYWORD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ),
+ Z1_KEYWORD_CALLBACK( "WeightVector", parse_weight_vector ),
+ Z1_KEYWORD_CALLBACK( "shareddict", parse_shared_dict ),
+#endif
+ Z1_KEYWORD_CALLBACK( 0, 0 )
+ };
+
+
+ static
+ FT_Error parse_dict( T1_Face face,
+ Z1_Loader* loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+ parser->cursor = base;
+ parser->limit = base + size;
+ parser->error = 0;
+
+ {
+ FT_Byte* cur = base;
+ FT_Byte* limit = cur + size;
+
+ for ( ;cur < limit; cur++ )
+ {
+ /* look for "FontDirectory", which causes problems on some fonts */
+ if ( *cur == 'F' && cur+25 < limit &&
+ strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ {
+ FT_Byte* cur2;
+
+ /* skip the "FontDirectory" keyword */
+ cur += 13;
+ cur2 = cur;
+
+ /* lookup the 'known' keyword */
+ while (cur < limit && *cur != 'k' && strncmp( (char*)cur, "known", 5 ) )
+ cur++;
+
+ if (cur < limit)
+ {
+ Z1_Token_Rec token;
+
+ /* skip the "known" keyword and the token following it */
+ cur += 5;
+ loader->parser.cursor = cur;
+ Z1_ToToken( &loader->parser, &token );
+
+ /* if the last token was an array, skip it !! */
+ if (token.type == t1_token_array)
+ cur2 = parser->cursor;
+ }
+ cur = cur2;
+ }
+ /* look for immediates */
+ else if (*cur == '/' && cur+2 < limit)
+ {
+ FT_Byte* cur2;
+ FT_Int len;
+
+ cur ++;
+ cur2 = cur;
+ while (cur2 < limit && is_alpha(*cur2)) cur2++;
+ len = cur2-cur;
+
+ if (len > 0 && len < 22)
+ {
+ if (!loader->fontdata)
+ {
+ if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+ loader->fontdata = 1;
+ }
+ else
+ {
+ /* now, compare the immediate name to the keyword table */
+ Z1_KeyWord* keyword = (Z1_KeyWord*)t1_keywords;
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+ name = (FT_Byte*)keyword->name;
+ if (!name) break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_Int)strlen((const char*)name) )
+ {
+ FT_Int n;
+ for ( n = 1; n < len; n++ )
+ if (cur[n] != name[n])
+ break;
+
+ if (n >= len)
+ {
+ /* we found it - run the parsing callback !! */
+ parser->cursor = cur2;
+ skip_whitespace( parser );
+ parser->error = t1_load_keyword( face, loader, keyword );
+ if (parser->error)
+ return parser->error;
+
+ cur = parser->cursor;
+ break;
+ }
+ }
+ keyword++;
+ }
+ }
+ }
+ }
+ }
+ }
+ return parser->error;
+ }
+
+ static
+ void t1_init_loader( Z1_Loader* loader, T1_Face face )
+ {
+ UNUSED(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;
+ loader->subrs.init = 0;
+ loader->fontdata = 0;
+ }
+
+ static
+ void t1_done_loader( Z1_Loader* loader )
+ {
+ Z1_Parser* parser = &loader->parser;
+
+ /* finalize tables */
+ Z1_Release_Table( &loader->encoding_table );
+ Z1_Release_Table( &loader->charstrings );
+ Z1_Release_Table( &loader->glyph_names );
+ Z1_Release_Table( &loader->subrs );
+
+ /* finalize parser */
+ Z1_Done_Parser( parser );
+ }
+
+ LOCAL_FUNC
+ FT_Error Z1_Open_Face( T1_Face face )
+ {
+ Z1_Loader loader;
+ Z1_Parser* parser;
+ T1_Font* type1 = &face->type1;
+ FT_Error error;
+
+ t1_init_loader( &loader, face );
+
+ /* default lenIV */
+ type1->private_dict.lenIV = 4;
+
+ parser = &loader.parser;
+ error = Z1_New_Parser( parser, face->root.stream, face->root.memory );
+ if (error) goto Exit;
+
+ error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+ if (error) goto Exit;
+
+ error = Z1_Get_Private_Dict( parser );
+ if (error) goto Exit;
+
+ error = parse_dict( face, &loader, parser->private_dict, parser->private_len );
+ if (error) goto Exit;
+
+ /* 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 = T1_Err_Invalid_File_Format;
+ }
+
+ if ( !loader.charstrings.init )
+ {
+ FT_ERROR(( "T1.Open_Face: no charstrings array in face !!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ loader.subrs.init = 0;
+ type1->num_subrs = loader.num_subrs;
+ type1->subrs_block = loader.subrs.block;
+ type1->subrs = loader.subrs.elements;
+ type1->subrs_len = loader.subrs.lengths;
+
+ loader.charstrings.init = 0;
+ type1->charstrings_block = loader.charstrings.block;
+ type1->charstrings = loader.charstrings.elements;
+ type1->charstrings_len = loader.charstrings.lengths;
+
+ /* we copy the glyph names "block" and "elements" fields */
+ /* but the "lengths" field must be released later.. */
+ type1->glyph_names_block = loader.glyph_names.block;
+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;
+ loader.glyph_names.block = 0;
+ loader.glyph_names.elements = 0;
+
+ /* we must now build type1.encoding when we have a custom */
+ /* array.. */
+ if ( type1->encoding_type == t1_encoding_array )
+ {
+ FT_Int charcode, index, min_char, max_char;
+ FT_Byte* char_name;
+ FT_Byte* glyph_name;
+
+ /* OK, we do the following : for each element in the encoding */
+ /* table, lookup the index of the glyph having the same name */
+ /* the index is then stored in type1.encoding.char_index, and */
+ /* a the name to type1.encoding.char_name */
+
+ min_char = +32000;
+ max_char = -32000;
+
+ charcode = 0;
+ for ( ; charcode < loader.encoding_table.num_elems; charcode++ )
+ {
+ type1->encoding.char_index[charcode] = 0;
+ type1->encoding.char_name [charcode] = ".notdef";
+
+ char_name = loader.encoding_table.elements[charcode];
+ if (char_name)
+ for ( index = 0; index < type1->num_glyphs; index++ )
+ {
+ glyph_name = (FT_Byte*)type1->glyph_names[index];
+ if ( strcmp( (const char*)char_name,
+ (const char*)glyph_name ) == 0 )
+ {
+ type1->encoding.char_index[charcode] = index;
+ type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+ if (charcode < min_char) min_char = charcode;
+ if (charcode > max_char) max_char = charcode;
+ break;
+ }
+ }
+ }
+ type1->encoding.code_first = min_char;
+ type1->encoding.code_last = max_char;
+ type1->encoding.num_chars = loader.num_chars;
+ }
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
--- /dev/null
+++ b/src/type1z/z1load.h
@@ -1,0 +1,77 @@
+/*******************************************************************
+ *
+ * t1load.h 2.0
+ *
+ * Type1 Loader.
+ *
+ * Copyright 1996-2000 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1LOAD_H
+#define T1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+#include <freetype/ftmm.h>
+#include <z1parse.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ typedef struct Z1_Loader_
+ {
+ Z1_Parser parser; /* parser used to read the stream */
+
+ FT_Int num_chars; /* number of characters in encoding */
+ Z1_Table encoding_table; /* Z1_Table used to store the */
+ /* encoding character names */
+
+ FT_Int num_glyphs;
+ Z1_Table glyph_names;
+ Z1_Table charstrings;
+
+ FT_Int num_subrs;
+ Z1_Table subrs;
+ FT_Bool fontdata;
+
+ } Z1_Loader;
+
+ LOCAL_DEF
+ FT_Error Z1_Open_Face( T1_Face face );
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ LOCAL_DEF
+ FT_Error Z1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master );
+
+ LOCAL_DEF
+ FT_Error Z1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ LOCAL_DEF
+ FT_Error Z1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+ LOCAL_DEF
+ void Z1_Done_Blend( T1_Face face );
+#endif
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/z1objs.c
@@ -1,0 +1,361 @@
+/*******************************************************************
+ *
+ * t1objs.c 1.0
+ *
+ * Type1 Objects manager.
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+#include <z1gload.h>
+#include <z1load.h>
+#include <freetype/internal/psnames.h>
+#include <z1afm.h>
+
+/* Required by tracing mode */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1objs
+
+/*******************************************************************
+ * *
+ * FACE FUNCTIONS *
+ * *
+ * *
+ *******************************************************************/
+
+/*******************************************************************
+ *
+ * <Function> Z1_Done_Face
+ *
+ * <Description>
+ * The face object destructor.
+ *
+ * <Input>
+ * face :: typeless pointer to the face object to destroy
+ *
+ * <Return>
+ * Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ void Z1_Done_Face( T1_Face face )
+ {
+ FT_Memory memory;
+ T1_Font* type1 = &face->type1;
+
+ if (face)
+ {
+ memory = face->root.memory;
+
+#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
+ /* release multiple masters information */
+ Z1_Done_Blend( face );
+ face->blend = 0;
+#endif
+
+ /* release font info strings */
+ {
+ T1_FontInfo* info = &type1->font_info;
+
+ FREE( info->version );
+ FREE( info->notice );
+ FREE( info->full_name );
+ FREE( info->family_name );
+ FREE( info->weight );
+ }
+
+ /* release top dictionary */
+ FREE( type1->charstrings_len );
+ FREE( type1->charstrings );
+ FREE( type1->glyph_names );
+
+ FREE( type1->subrs );
+ FREE( type1->subrs_len );
+
+ FREE( type1->subrs_block );
+ FREE( type1->charstrings_block );
+ FREE( type1->glyph_names_block );
+
+ FREE( type1->encoding.char_index );
+ FREE( type1->font_name );
+
+#ifndef Z1_CONFIG_OPTION_NO_AFM
+ /* release afm data if present */
+ if ( face->afm_data)
+ Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+ FREE( face->unicode_map.maps );
+ face->unicode_map.num_maps = 0;
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+/*******************************************************************
+ *
+ * <Function> Z1_Init_Face
+ *
+ * <Description>
+ * The face object constructor.
+ *
+ * <Input>
+ * face :: face record to build
+ * Input :: input stream where to load font data
+ *
+ * <Return>
+ * Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ FT_Error Z1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ PSNames_Interface* psnames;
+
+ UNUSED(num_params);
+ UNUSED(params);
+ UNUSED(face_index);
+ UNUSED(stream);
+
+ face->root.num_faces = 1;
+
+ psnames = (PSNames_Interface*)face->psnames;
+ if (!psnames)
+ {
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY(face), "psnames" );
+
+ face->psnames = psnames;
+ }
+
+ /* open the tokenizer, this will also check the font format */
+ error = Z1_Open_Face( face );
+ if (error) goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if (face_index < 0)
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "T1.Init_Face : invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Now, load the font program into the face object */
+ {
+ /* Init the face object fields */
+ /* Now set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+
+ root->num_glyphs = face->type1.num_glyphs;
+ root->num_charmaps = 1;
+
+ root->face_index = face_index;
+ root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ if ( face->type1.font_info.is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( face->blend )
+ root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+ /* XXX : TO DO - add kerning with .afm support */
+
+ /* get style name - be careful, some broken fonts only */
+ /* have a /FontName dictionary entry .. !! */
+ root->family_name = face->type1.font_info.family_name;
+ if (root->family_name)
+ {
+ char* full = face->type1.font_info.full_name;
+ char* family = root->family_name;
+
+ while ( *family && *full == *family )
+ {
+ family++;
+ full++;
+ }
+
+ root->style_name = ( *full == ' ' ? full+1 : "Regular" );
+ }
+ else
+ {
+ /* do we have a /FontName ?? */
+ if (face->type1.font_name)
+ {
+ root->family_name = face->type1.font_name;
+ root->style_name = "Regular";
+ }
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox = face->type1.font_bbox;
+ root->units_per_EM = 1000;
+ root->ascender = (FT_Short)face->type1.font_bbox.yMax;
+ root->descender = -(FT_Short)face->type1.font_bbox.yMin;
+ root->height = ((root->ascender + root->descender)*12)/10;
+
+ /* now compute the maximum advance width */
+
+ root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+ /* compute max advance width for proportional fonts */
+ if (!face->type1.font_info.is_fixed_pitch)
+ {
+ FT_Int max_advance;
+
+ error = Z1_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if (!error)
+ root->max_advance_width = max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+ root->underline_position = face->type1.font_info.underline_position;
+ root->underline_thickness = face->type1.font_info.underline_thickness;
+
+ root->max_points = 0;
+ root->max_contours = 0;
+ }
+ }
+
+ /* charmap support - synthetize unicode charmap when possible */
+ {
+ FT_Face root = &face->root;
+ FT_CharMap charmap = face->charmaprecs;
+
+ /* synthesize 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];
+ }
+ Exit:
+ return error;
+ }
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Init_Driver
+ *
+ * <Description>
+ * Initialise a given Type 1 driver object
+ *
+ * <Input>
+ * driver :: handle to target driver object
+ *
+ * <Return>
+ * Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_FUNC
+ FT_Error Z1_Init_Driver( Z1_Driver driver )
+ {
+ UNUSED(driver);
+ return T1_Err_Ok;
+ }
+
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Done_Driver
+ *
+ * <Description>
+ * finalise a given Type 1 driver
+ *
+ * <Input>
+ * driver :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+ LOCAL_DEF
+ void Z1_Done_Driver( Z1_Driver driver )
+ {
+ UNUSED(driver);
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/z1objs.h
@@ -1,0 +1,215 @@
+/*******************************************************************
+ *
+ * t1objs.h 1.0
+ *
+ * Type1 objects definition.
+ *
+ * Copyright 1996-1999 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#ifndef T1OBJS_H
+#define T1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* The following structures must be defined by the hinter */
+ typedef struct Z1_Size_Hints_ Z1_Size_Hints;
+ typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints;
+
+ /***********************************************************************/
+ /* */
+ /* <Type> Z1_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct Z1_DriverRec_ *Z1_Driver;
+
+
+ /***********************************************************************/
+ /* */
+ /* <Type> Z1_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct Z1_SizeRec_* Z1_Size;
+
+
+ /***********************************************************************/
+ /* */
+ /* <Type> Z1_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot;
+
+
+ /***********************************************************************/
+ /* */
+ /* <Type> Z1_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables.. */
+ /* */
+ typedef struct Z1_CharMapRec_* Z1_CharMap;
+
+
+
+ /**************************************************************************/
+ /* */
+ /* NOW BEGINS THE TYPE1 SPECIFIC STUFF .............................. */
+ /* */
+ /**************************************************************************/
+
+
+ /***************************************************/
+ /* */
+ /* Z1_Size : */
+ /* */
+ /* Type 1 size record.. */
+ /* */
+
+ typedef struct Z1_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+ Z1_Size_Hints* hints; /* defined in the hinter. This allows */
+ /* us to experiment with different */
+ /* hinting schemes without having to */
+ /* change 't1objs' each time.. */
+ } Z1_SizeRec;
+
+
+
+ /***************************************************/
+ /* */
+ /* Z1_GlyphSlot : */
+ /* */
+ /* TrueDoc glyph record.. */
+ /* */
+
+ typedef struct Z1_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ Z1_Glyph_Hints* hints; /* defined in the hinter */
+
+ } Z1_GlyphSlotRec;
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Init_Face
+ *
+ * <Description>
+ * Initialise a given Type 1 face object
+ *
+ * <Input>
+ * face_index :: index of font face in resource
+ * resource :: source font resource
+ * face :: face record to build
+ *
+ * <Return>
+ * Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_DEF
+ FT_Error Z1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Done_Face
+ *
+ * <Description>
+ * Finalise a given face object
+ *
+ * <Input>
+ * face :: handle to the face object to destroy
+ *
+ ******************************************************************/
+
+ LOCAL_DEF
+ void Z1_Done_Face( T1_Face face );
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Init_Driver
+ *
+ * <Description>
+ * Initialise a given Type 1 driver object
+ *
+ * <Input>
+ * driver :: handle to target driver object
+ *
+ * <Return>
+ * Error code.
+ *
+ ******************************************************************/
+
+ LOCAL_DEF
+ FT_Error Z1_Init_Driver( Z1_Driver driver );
+
+
+
+/*******************************************************************
+ *
+ * <Function> Z1_Done_Driver
+ *
+ * <Description>
+ * finalise a given Type 1 driver
+ *
+ * <Input>
+ * driver :: handle to target Type 1 driver
+ *
+ ******************************************************************/
+
+ LOCAL_DEF
+ void Z1_Done_Driver( Z1_Driver driver );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1z/z1parse.c
@@ -1,0 +1,1269 @@
+/*******************************************************************
+ *
+ * t1parse.c 2.0
+ *
+ * Type1 parser.
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ * The Type 1 parser is in charge of the following:
+ *
+ * - provide an implementation of a growing sequence of
+ * objects called a Z1_Table (used to build various tables
+ * needed by the loader).
+ *
+ * - opening .pfb and .pfa files to extract their top-level
+ * and private dictionaries
+ *
+ * - read numbers, arrays & strings from any dictionary
+ *
+ * See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+#include <z1parse.h>
+
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_t1load
+
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/***** *****/
+/***** IMPLEMENTATION OF Z1_TABLE OBJECT *****/
+/***** *****/
+/***** *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+
+/*************************************************************************/
+/* */
+/* <Function> Z1_New_Table */
+/* */
+/* <Description> */
+/* Initialise a Z1_Table. */
+/* */
+/* <Input> */
+/* table :: address of target table */
+/* count :: table size = maximum number of elements */
+/* memory :: memory object to use for all subsequent reallocations */
+/* */
+/* <Return> */
+/* Error code. 0 means success */
+/* */
+
+ LOCAL_FUNC
+ FT_Error Z1_New_Table( Z1_Table* table,
+ FT_Int count,
+ FT_Memory memory )
+ {
+ FT_Error error;
+
+ table->memory = memory;
+ if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
+ ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
+ goto Exit;
+
+ table->max_elems = count;
+ table->init = 0xdeadbeef;
+ table->num_elems = 0;
+ table->block = 0;
+ table->capacity = 0;
+ table->cursor = 0;
+
+ Exit:
+ if (error) FREE(table->elements);
+
+ return error;
+ }
+
+
+
+/*************************************************************************/
+/* */
+/* <Function> Z1_Add_Table */
+/* */
+/* <Description> */
+/* Adds an object to a Z1_Table, possibly growing its memory block */
+/* */
+/* <Input> */
+/* table :: target table */
+/* index :: index of object in table */
+/* object :: address of object to copy in memory */
+/* length :: length in bytes of source object */
+/* */
+/* <Return> */
+/* Error code. 0 means success. An error is returned when a */
+/* realloc failed.. */
+/* */
+
+
+ static void shift_elements( Z1_Table* table, FT_Byte* old_base )
+ {
+ FT_Long delta = table->block - old_base;
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+ if (delta)
+ for ( ; offset < limit; offset++ )
+ {
+ if (offset[0])
+ offset[0] += delta;
+ }
+ }
+
+ static
+ FT_Error reallocate_t1_table( Z1_Table* table,
+ FT_Int new_size )
+ {
+ FT_Memory memory = table->memory;
+ FT_Byte* old_base = table->block;
+ FT_Error error;
+
+ /* realloc the base block */
+ if ( REALLOC( table->block, table->capacity, new_size ) )
+ return error;
+
+ table->capacity = new_size;
+
+ /* shift all offsets when needed */
+ if (old_base)
+ shift_elements( table, old_base );
+
+ return T1_Err_Ok;
+ }
+
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Add_Table( Z1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length )
+ {
+ if (index < 0 || index > table->max_elems)
+ {
+ FT_ERROR(( "T1.Add_Table: invalid index\n" ));
+ return T1_Err_Syntax_Error;
+ }
+
+ /* grow the base block if needed */
+ if ( table->cursor + length > table->capacity )
+ {
+ FT_Error error;
+ FT_Int new_size = table->capacity;
+
+ while ( new_size < table->cursor+length )
+ new_size += 1024;
+
+ error = reallocate_t1_table( table, new_size );
+ if (error) return error;
+ }
+
+ /* add the object to the base block and adjust offset */
+ table->elements[ index ] = table->block + table->cursor;
+ table->lengths [ index ] = length;
+ MEM_Copy( table->block + table->cursor, object, length );
+
+ table->cursor += length;
+ return T1_Err_Ok;
+ }
+
+
+/*************************************************************************/
+/* */
+/* <Function> Z1_Done_Table */
+/* */
+/* <Description> */
+/* Finalise a Z1_Table. (realloc it to its current cursor). */
+/* */
+/* <Input> */
+/* table :: target table */
+/* */
+/* <Note> */
+/* This function does NOT release the heap's memory block. It is up */
+/* to the caller to clean it, or reference it in its own structures. */
+/* */
+#if 0
+ LOCAL_FUNC
+ void Z1_Done_Table( Z1_Table* table )
+ {
+ FT_Memory memory = table->memory;
+ FT_Error error;
+ FT_Byte* old_base;
+
+ /* should never fail, as rec.cursor <= rec.size */
+ old_base = table->block;
+ if (!old_base)
+ return;
+
+ (void)REALLOC( table->block, table->capacity, table->cursor );
+ table->capacity = table->cursor;
+
+ if (old_base != table->block)
+ shift_elements( table, old_base );
+ }
+#endif
+
+ LOCAL_FUNC
+ void Z1_Release_Table( Z1_Table* table )
+ {
+ FT_Memory memory = table->memory;
+
+ if (table->init == (FT_Long)0xdeadbeef)
+ {
+ FREE( table->block );
+ FREE( table->elements );
+ FREE( table->lengths );
+ table->init = 0;
+ }
+ }
+
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+/***** *****/
+/***** INPUT STREAM PARSER *****/
+/***** *****/
+/***** *****/
+/*************************************************************************/
+/*************************************************************************/
+/*************************************************************************/
+
+ #define IS_Z1_WHITESPACE(c) ( (c) == ' ' || (c) == '\t' )
+ #define IS_Z1_LINESPACE(c) ( (c) == '\r' || (c) == '\n' )
+
+ #define IS_Z1_SPACE(c) ( IS_Z1_WHITESPACE(c) || IS_Z1_LINESPACE(c) )
+
+ LOCAL_FUNC
+ void Z1_Skip_Spaces( Z1_Parser* parser )
+ {
+ FT_Byte* cur = parser->cursor;
+ FT_Byte* limit = parser->limit;
+
+ while (cur < limit)
+ {
+ FT_Byte c = *cur;
+ if (!IS_Z1_SPACE(c))
+ break;
+ cur++;
+ }
+ parser->cursor = cur;
+ }
+
+ LOCAL_FUNC
+ void Z1_ToToken( Z1_Parser* parser,
+ Z1_Token_Rec* token )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_Byte starter, ender;
+ FT_Int embed;
+
+ token->type = t1_token_none;
+ token->start = 0;
+ token->limit = 0;
+
+ /* first of all, skip space */
+ Z1_Skip_Spaces(parser);
+
+ cur = parser->cursor;
+ limit = parser->limit;
+
+ if ( cur < limit )
+ {
+ switch (*cur)
+ {
+ /************* check for strings ***********************/
+ case '(':
+ token->type = t1_token_string;
+ ender = ')';
+ goto Lookup_Ender;
+
+ /************* check for programs/array ****************/
+ case '{':
+ token->type = t1_token_array;
+ ender = '}';
+ goto Lookup_Ender;
+
+ /************* check for table/array ******************/
+ case '[':
+ token->type = t1_token_array;
+ ender = ']';
+
+ Lookup_Ender:
+ embed = 1;
+ starter = *cur++;
+ token->start = cur;
+ while (cur < limit)
+ {
+ if (*cur == starter)
+ embed++;
+ else if (*cur == ender)
+ {
+ embed--;
+ if (embed <= 0)
+ {
+ token->limit = cur++;
+ break;
+ }
+ }
+ cur++;
+ }
+ break;
+
+ /* **************** otherwise, it's any token **********/
+ default:
+ token->start = cur++;
+ token->type = t1_token_any;
+ while (cur < limit && !IS_Z1_SPACE(*cur))
+ cur++;
+
+ token->limit = cur;
+ }
+
+ if (!token->limit)
+ {
+ token->start = 0;
+ token->type = t1_token_none;
+ }
+
+ parser->cursor = cur;
+ }
+ }
+
+
+ LOCAL_FUNC
+ void Z1_ToTokenArray( Z1_Parser* parser,
+ Z1_Token_Rec* tokens,
+ FT_UInt max_tokens,
+ FT_Int *pnum_tokens )
+ {
+ Z1_Token_Rec master;
+
+ *pnum_tokens = -1;
+
+ Z1_ToToken( parser, &master );
+ if (master.type == t1_token_array)
+ {
+ FT_Byte* old_cursor = parser->cursor;
+ FT_Byte* old_limit = parser->limit;
+ Z1_Token_Rec* cur = tokens;
+ Z1_Token_Rec* limit = cur + max_tokens;
+
+ parser->cursor = master.start;
+ parser->limit = master.limit;
+
+ while (parser->cursor < parser->limit)
+ {
+ Z1_Token_Rec token;
+
+ Z1_ToToken( parser, &token );
+ if (!token.type)
+ break;
+
+ if (cur < limit)
+ *cur = token;
+
+ cur++;
+ }
+
+ *pnum_tokens = cur - tokens;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+ }
+ }
+
+
+ static
+ FT_Long t1_toint( FT_Byte* *cursor,
+ FT_Byte* limit )
+ {
+ FT_Long result = 0;
+ FT_Byte* cur = *cursor;
+ FT_Byte c, d;
+
+ for (; cur < limit; cur++)
+ {
+ c = *cur;
+ d = (FT_Byte)(c - '0');
+ if (d < 10) break;
+
+ if ( c=='-' )
+ {
+ cur++;
+ break;
+ }
+ }
+
+ if (cur < limit)
+ {
+ do
+ {
+ d = (FT_Byte)(cur[0] - '0');
+ if (d >= 10)
+ break;
+
+ result = result*10 + d;
+ cur++;
+
+ } while (cur < limit);
+
+ if (c == '-')
+ result = -result;
+ }
+
+ *cursor = cur;
+ return result;
+ }
+
+
+ static
+ FT_Long t1_tofixed( FT_Byte* *cursor,
+ FT_Byte* limit,
+ FT_Long power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Long num, divider, result;
+ FT_Int sign = 0;
+ FT_Byte d;
+
+ if (cur >= limit) return 0;
+
+ /* first of all, read the integer part */
+ result = t1_toint( &cur, limit ) << 16;
+ num = 0;
+ divider = 1;
+
+ if (result < 0)
+ {
+ sign = 1;
+ result = -result;
+ }
+ if (cur >= limit) goto Exit;
+
+ /* read decimal part, if any */
+ if (*cur == '.' && cur+1 < limit)
+ {
+ cur++;
+
+ for (;;)
+ {
+ d = (FT_Byte)(*cur - '0');
+ if (d >= 10) break;
+
+ if (divider < 10000000L)
+ {
+ num = num*10 + d;
+ divider *= 10;
+ }
+ cur++;
+ if (cur >= limit) break;
+ }
+ }
+
+ /* read exponent, if any */
+ if ( cur+1 < limit && (*cur == 'e' || *cur == 'E'))
+ {
+ cur++;
+ power_ten += t1_toint( &cur, limit );
+ }
+
+ Exit:
+ /* raise to power of ten if needed */
+ while (power_ten > 0)
+ {
+ result = result*10;
+ num = num*10;
+ power_ten--;
+ }
+
+ while (power_ten < 0)
+ {
+ result = result/10;
+ divider = divider*10;
+ power_ten++;
+ }
+
+ if (num)
+ result += FT_DivFix( num, divider );
+
+ if (sign)
+ result = -result;
+
+ *cursor = cur;
+ return result;
+ }
+
+
+ static
+ FT_Int t1_tocoordarray( FT_Byte* *cursor,
+ FT_Byte* limit,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+ if (cur >= limit) goto Exit;
+
+ /* check for the beginning of an array. If not, only one number will be read */
+ c = *cur;
+ ender = 0;
+
+ if (c == '[')
+ ender = ']';
+
+ if (c == '{')
+ ender = '}';
+
+ if (ender)
+ cur++;
+
+ /* now, read the coordinates */
+ for ( ; cur < limit; )
+ {
+ /* 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;
+
+ coords[count] = (FT_Short)(t1_tofixed(&cur,limit,0) >> 16);
+ count++;
+
+ if (!ender)
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+ return count;
+ }
+
+
+
+ static
+ FT_Int t1_tofixedarray( FT_Byte* *cursor,
+ FT_Byte* limit,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int count = 0;
+ FT_Byte c, ender;
+
+ if (cur >= limit) goto Exit;
+
+ /* check for the beginning of an array. If not, only one number will be read */
+ c = *cur;
+ ender = 0;
+
+ if (c == '[')
+ ender = ']';
+
+ if (c == '{')
+ ender = '}';
+
+ if (ender)
+ cur++;
+
+ /* now, read the values */
+ for ( ; cur < limit; )
+ {
+ /* 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;
+
+ values[count] = t1_tofixed(&cur,limit,power_ten);
+ count++;
+
+ if (!ender)
+ break;
+ }
+
+ Exit:
+ *cursor = cur;
+ return count;
+ }
+
+
+#if 0
+ static
+ FT_String* t1_tostring( FT_Byte* *cursor, FT_Byte* limit, FT_Memory memory )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Int len = 0;
+ FT_Int count;
+ FT_String* result;
+ FT_Error error;
+
+ /* 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;
+
+ /* then, count its length */
+ for ( ; cur < limit; cur++ )
+ {
+ if (*cur == '(')
+ count++;
+
+ else if (*cur == ')')
+ {
+ count--;
+ if (count < 0)
+ break;
+ }
+ }
+
+ len = cur - *cursor;
+ if (cur >= limit || ALLOC(result,len+1)) return 0;
+
+ /* now copy the string */
+ MEM_Copy( result, *cursor, len );
+ result[len] = '\0';
+ *cursor = cur;
+ return result;
+ }
+#endif
+
+ static
+ int t1_tobool( FT_Byte* *cursor, FT_Byte* limit )
+ {
+ FT_Byte* cur = *cursor;
+ FT_Bool result = 0;
+
+ /* return 1 if we find a "true", 0 otherwise */
+ if ( cur+3 < limit &&
+ cur[0] == 't' &&
+ cur[1] == 'r' &&
+ cur[2] == 'u' &&
+ cur[3] == 'e' )
+ {
+ result = 1;
+ cur += 5;
+ }
+ else if ( cur+4 < limit &&
+ cur[0] == 'f' &&
+ cur[1] == 'a' &&
+ cur[2] == 'l' &&
+ cur[3] == 's' &&
+ cur[4] == 'e' )
+ {
+ result = 0;
+ cur += 6;
+ }
+ *cursor = cur;
+ return result;
+ }
+
+
+
+ /* Loads a simple field (i.e. non-table) into the current list of objects */
+ LOCAL_FUNC
+ FT_Error Z1_Load_Field( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ Z1_Token_Rec token;
+ FT_Byte* cur;
+ FT_Byte* limit;
+ FT_UInt count;
+ FT_UInt index;
+ FT_Error error;
+
+ Z1_ToToken( parser, &token );
+ if (!token.type)
+ goto Fail;
+
+ count = 1;
+ index = 0;
+ cur = token.start;
+ limit = token.limit;
+
+ if (token.type == t1_token_array)
+ {
+ /* if this is an array, and we have no blend, an error occurs */
+ if (max_objects == 0)
+ goto Fail;
+
+ count = max_objects;
+ index = 1;
+ }
+
+ for ( ; count > 0; count--, index++ )
+ {
+ FT_Byte* q = (FT_Byte*)objects[index] + field->offset;
+ FT_Long val;
+ FT_String* string;
+
+ switch (field->type)
+ {
+ case t1_field_bool:
+ {
+ val = t1_tobool( &cur, limit );
+ goto Store_Integer;
+ }
+
+ case t1_field_fixed:
+ {
+ val = t1_tofixed( &cur, limit, 3 );
+ goto Store_Integer;
+ }
+
+ case t1_field_integer:
+ {
+ val = t1_toint( &cur, limit );
+ Store_Integer:
+ switch (field->size)
+ {
+ case 1: *(FT_Byte*)q = (FT_Byte)val; break;
+ case 2: *(FT_UShort*)q = (FT_UShort)val; break;
+ default: *(FT_Long*)q = val;
+ }
+ }
+ break;
+
+ case t1_field_string:
+ {
+ FT_Memory memory = parser->memory;
+ FT_UInt len = limit-cur;
+
+ if ( ALLOC( string, len+1 ) )
+ goto Exit;
+
+ MEM_Copy( string, cur, len );
+ string[len] = 0;
+
+ *(FT_String**)q = string;
+ }
+ break;
+
+ default:
+ /* an error occured */
+ goto Fail;
+ }
+ }
+ if (pflags)
+ *pflags |= 1L << field->flag_bit;
+ error = 0;
+
+ Exit:
+ return error;
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+#define T1_MAX_TABLE_ELEMENTS 32
+
+ LOCAL_FUNC
+ FT_Error Z1_Load_Field_Table( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags )
+ {
+ Z1_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
+ Z1_Token_Rec* token;
+ FT_Int num_elements;
+ FT_Error error = 0;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ Z1_Field_Rec fieldrec = *(Z1_Field_Rec*)field;
+
+ Z1_ToTokenArray( parser, elements, 32, &num_elements );
+ if (num_elements < 0)
+ goto Fail;
+
+ if (num_elements > T1_MAX_TABLE_ELEMENTS)
+ num_elements = T1_MAX_TABLE_ELEMENTS;
+
+ old_cursor = parser->cursor;
+ old_limit = parser->limit;
+
+ /* we store the elements count */
+ *(FT_Byte*)((FT_Byte*)objects[0] + field->count_offset) = num_elements;
+
+ /* we now load each element, adjusting the field.offset on each one */
+ token = elements;
+ for ( ; num_elements > 0; num_elements--, token++ )
+ {
+ parser->cursor = token->start;
+ parser->limit = token->limit;
+ Z1_Load_Field( parser, &fieldrec, objects, max_objects, 0 );
+ fieldrec.offset += fieldrec.size;
+ }
+
+ if (pflags)
+ *pflags |= 1L << field->flag_bit;
+
+ parser->cursor = old_cursor;
+ parser->limit = old_limit;
+
+ Exit:
+ return error;
+ Fail:
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+
+
+
+
+
+
+ LOCAL_FUNC
+ FT_Long Z1_ToInt ( Z1_Parser* parser )
+ {
+ return t1_toint( &parser->cursor, parser->limit );
+ }
+
+
+ LOCAL_FUNC
+ FT_Long Z1_ToFixed( Z1_Parser* parser, FT_Int power_ten )
+ {
+ return t1_tofixed( &parser->cursor, parser->limit, power_ten );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int Z1_ToCoordArray( Z1_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords )
+ {
+ return t1_tocoordarray( &parser->cursor, parser->limit, max_coords, coords );
+ }
+
+
+ LOCAL_FUNC
+ FT_Int Z1_ToFixedArray( Z1_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten )
+ {
+ return t1_tofixedarray( &parser->cursor, parser->limit, max_values, values, power_ten );
+ }
+
+
+#if 0
+ LOCAL_FUNC
+ FT_String* Z1_ToString( Z1_Parser* parser )
+ {
+ return t1_tostring( &parser->cursor, parser->limit, parser->memory );
+ }
+
+
+ LOCAL_FUNC
+ FT_Bool Z1_ToBool( Z1_Parser* parser )
+ {
+ return t1_tobool( &parser->cursor, parser->limit );
+ }
+#endif
+
+
+ static
+ FT_Error read_pfb_tag( FT_Stream stream, FT_UShort *tag, FT_Long* size )
+ {
+ FT_Error error;
+
+ if (READ_UShort(*tag)) goto Exit;
+ if (*tag == 0x8001 || *tag == 0x8002)
+ {
+ FT_Long asize;
+
+ if (READ_ULong(asize)) goto Exit;
+
+ /* swap between big and little endianness */
+ *size = ((asize & 0xFF000000) >> 24) |
+ ((asize & 0x00FF0000) >> 8 ) |
+ ((asize & 0x0000FF00) << 8 ) |
+ ((asize & 0x000000FF) << 24);
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+ LOCAL_FUNC
+ FT_Error Z1_New_Parser( Z1_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+ parser->stream = stream;
+ parser->memory = memory;
+ parser->base_len = 0;
+ parser->base_dict = 0;
+ parser->private_len = 0;
+ parser->private_dict = 0;
+ parser->in_pfb = 0;
+ parser->in_memory = 0;
+ parser->single_block = 0;
+
+ parser->cursor = 0;
+ parser->limit = 0;
+
+ /******************************************************************/
+ /* */
+ /* Here's a short summary of what is going on : */
+ /* */
+ /* When creating a new Type 1 parser, we try to locate and */
+ /* load the base dictionary when this is possible (i.e. for */
+ /* .pfb files). Otherwise, we load the whole font in memory. */
+ /* */
+ /* When "loading" the base dictionary, we only setup pointers */
+ /* in the case of a memory-based stream. Otherwise, we allocate */
+ /* and load the base dict in it. */
+ /* */
+ /* parser->in_pfb is set when we are in a binary (".pfb") font */
+ /* parser->in_memory is set when we have a memory stream. */
+ /* */
+
+ /* try to compute the size of the base dictionary */
+ /* look for a Postscript binary file tag, i.e 0x8001 */
+ if ( FILE_Seek(0L) )
+ goto Exit;
+
+ error = read_pfb_tag( stream, &tag, &size );
+ if (error) goto Exit;
+
+ if (tag != 0x8001)
+ {
+ /* assume that this is a PFA file for now, an error will */
+ /* be produced later when more things are checked */
+ (void)FILE_Seek(0L);
+ size = stream->size;
+ }
+ 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 = (FT_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 = FT_Err_Unknown_File_Format;
+ }
+ else
+ {
+ parser->cursor = parser->base_dict;
+ parser->limit = parser->cursor + parser->base_len;
+ }
+ }
+
+ Exit:
+ if (error && !parser->in_memory)
+ FREE( parser->base_dict );
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_Done_Parser( Z1_Parser* parser )
+ {
+ FT_Memory memory = parser->memory;
+
+ /* always free the private dictionary */
+ FREE( parser->private_dict );
+
+ /* free the base dictionary only when we have a disk stream */
+ if (!parser->in_memory)
+ FREE( parser->base_dict );
+ }
+
+
+ /* return the value of an hexadecimal digit */
+ static
+ int hexa_value( char c )
+ {
+ unsigned int d;
+
+ d = (unsigned int)(c-'0');
+ if ( d <= 9 ) return (int)d;
+
+ d = (unsigned int)(c-'a');
+ if ( d <= 5 ) return (int)(d+10);
+
+ d = (unsigned int)(c-'A');
+ if ( d <= 5 ) return (int)(d+10);
+
+ return -1;
+ }
+
+
+ LOCAL_FUNC
+ void Z1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed )
+ {
+ while ( length > 0 )
+ {
+ FT_Byte plain;
+
+ plain = (*buffer ^ (seed >> 8));
+ seed = (*buffer+seed)*52845+22719;
+ *buffer++ = plain;
+ length--;
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_Error Z1_Get_Private_Dict( Z1_Parser* parser )
+ {
+ FT_Stream stream = parser->stream;
+ FT_Memory memory = parser->memory;
+ FT_Error error = 0;
+ FT_Long size;
+
+ if (parser->in_pfb)
+ {
+ /* in the case of the PFB format, the private dictionary can be */
+ /* made of several segments. We thus first read the number of */
+ /* segments to compute the total size of the private dictionary */
+ /* then re-read them into memory.. */
+ FT_Long start_pos = FILE_Pos();
+ FT_UShort tag;
+ FT_Long size;
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag(stream, &tag, &size);
+ if (error) goto Fail;
+
+ if (tag != 0x8002)
+ break;
+
+ parser->private_len += size;
+
+ if ( FILE_Skip(size) )
+ goto Fail;
+ }
+
+ /* Check that we have a private dictionary there */
+ /* and allocate private dictionary buffer */
+ if ( parser->private_len == 0 )
+ {
+ FT_ERROR(( "T1.Open_Private: invalid private dictionary section\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( FILE_Seek( start_pos ) ||
+ ALLOC( parser->private_dict, parser->private_len ) )
+ goto Fail;
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if (error || tag != 0x8002) { error = 0; break; }
+
+ if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+ goto Fail;
+
+ parser->private_len += size;
+ }
+ }
+ else
+ {
+ /* we have already "loaded" the whole PFA font file in memory */
+ /* if this is a memory resource, allocate a new block to hold */
+ /* the private dict. Otherwise, simply overwrite into the */
+ /* base dict block in the heap.. */
+
+ /* first of all, look at the "eexec" keyword */
+ FT_Byte* cur = parser->base_dict;
+ FT_Byte* limit = cur + parser->base_len;
+ FT_Byte c;
+
+ for (;;)
+ {
+ c = cur[0];
+ if (c == 'e' && cur+9 < limit) /* 9 = 5 letters for 'eexec' + newline + 4 chars */
+ {
+ if ( cur[1] == 'e' && cur[2] == 'x' &&
+ cur[3] == 'e' && cur[4] == 'c' )
+ {
+ cur += 6; /* we skip the newling after the "eexec" */
+
+ /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n, we need to skip */
+ /* the extra \n when we find it.. */
+ if (cur[0] == '\n')
+ cur++;
+
+ break;
+ }
+ }
+ cur++;
+ if (cur >= limit)
+ {
+ FT_ERROR(("T1.Open_Private: could not find 'eexec' keyword\n"));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ /* now determine wether where to write the _encrypted_ binary private */
+ /* dictionary. We overwrite the base dictionary for disk-based resources */
+ /* and allocate a new block otherwise */
+
+ size = parser->base_len - (cur-parser->base_dict);
+
+ if ( parser->in_memory )
+ {
+ /* note that we allocate one more byte to put a terminating '0' */
+ if (ALLOC( parser->private_dict, size+1 )) goto Fail;
+ parser->private_len = size;
+ }
+ else
+ {
+ parser->single_block = 1;
+ parser->private_dict = parser->base_dict;
+ parser->private_len = size;
+ parser->base_dict = 0;
+ parser->base_len = 0;
+ }
+
+ /* now determine wether the private dictionary is encoded in binary */
+ /* or hexadecimal ASCII format.. */
+ /* and decode it accordingly */
+
+ /* we need to access the next 4 bytes (after the final \r following */
+ /* the 'eexec' keyword..) if they all are hexadecimal digits, then */
+ /*we have a case of ASCII storage.. */
+
+ if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+ hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+ {
+ /* binary encoding - "simply" copy the private dict */
+ MEM_Copy( parser->private_dict, cur, size );
+ }
+ else
+ {
+ /* ASCII hexadecimal encoding.. This blows goats !!.. */
+
+ FT_Byte* write;
+ FT_Int count;
+
+ write = parser->private_dict;
+ count = 0;
+
+ for ( ;cur < limit; cur++)
+ {
+ int hex1;
+
+ /* check for newline */
+ if (cur[0] == '\r' || cur[0] == '\n')
+ continue;
+
+ /* exit if we have a non-hexadecimal digit that isn't a newline */
+ hex1 = hexa_value(cur[0]);
+ if (hex1 < 0 || cur+1 >= limit)
+ break;
+
+ /* otherwise, store byte */
+ *write++ = (hex1 << 4) | hexa_value(cur[1]);
+ count++;
+ cur++;
+ }
+
+ /* put a safeguard */
+ parser->private_len = write - parser->private_dict;
+ *write++ = 0;
+ }
+ }
+
+ /* we now decrypt the encoded binary private dictionary */
+ Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+ parser->cursor = parser->private_dict;
+ parser->limit = parser->cursor + parser->private_len;
+
+ Fail:
+ Exit:
+ return error;
+ }
+
--- /dev/null
+++ b/src/type1z/z1parse.h
@@ -1,0 +1,348 @@
+/*******************************************************************
+ *
+ * t1parse.h 2.0
+ *
+ * Type1 parser.
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ * The Type 1 parser is in charge of the following:
+ *
+ * - provide an implementation of a growing sequence of
+ * objects called a Z1_Table (used to build various tables
+ * needed by the loader).
+ *
+ * - opening .pfb and .pfa files to extract their top-level
+ * and private dictionaries
+ *
+ * - read numbers, arrays & strings from any dictionary
+ *
+ * See "t1load.c" to see how data is loaded from the font file
+ *
+ ******************************************************************/
+
+#ifndef T1PARSE_H
+#define T1PARSE_H
+
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /* simple enumeration type used to identify token types */
+ typedef enum Z1_Token_Type_
+ {
+ t1_token_none = 0,
+ t1_token_any,
+ t1_token_string,
+ t1_token_array,
+
+ /* do not remove */
+ t1_token_max
+
+ } Z1_Token_Type;
+
+ /* a simple structure used to identify tokens */
+ typedef struct Z1_Token_Rec_
+ {
+ FT_Byte* start; /* first character of token in input stream */
+ FT_Byte* limit; /* first character after the token */
+ Z1_Token_Type type; /* type of token.. */
+
+ } Z1_Token_Rec;
+
+ /* enumeration type used to identify object fields */
+ typedef enum Z1_Field_Type_
+ {
+ t1_field_none = 0,
+ t1_field_bool,
+ t1_field_integer,
+ t1_field_fixed,
+ t1_field_string,
+ t1_field_integer_array,
+ t1_field_fixed_array,
+
+ /* do not remove */
+ t1_field_max
+
+ } Z1_Field_Type;
+
+ /* structure type used to model object fields */
+ typedef struct Z1_Field_Rec_
+ {
+ Z1_Field_Type type; /* type of field */
+ FT_UInt offset; /* offset of field in object */
+ FT_UInt size; /* size of field in bytes */
+ FT_UInt array_max; /* maximum number of elements for array */
+ FT_UInt count_offset; /* offset of element count for arrays */
+ FT_Int flag_bit; /* bit number for field flag */
+
+ } Z1_Field_Rec;
+
+#define Z1_FIELD_REF(s,f) (((s*)0)->f)
+
+#define Z1_FIELD_BOOL( _ftype, _fname ) \
+ { t1_field_bool, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define Z1_FIELD_NUM( _ftype, _fname ) \
+ { t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define Z1_FIELD_FIXED( _ftype, _fname, _power ) \
+ { t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define Z1_FIELD_STRING( _ftype, _fname ) \
+ { t1_field_string, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)), \
+ 0, 0, 0 }
+
+#define Z1_FIELD_NUM_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fcount), \
+ 0 }
+
+#define Z1_FIELD_FIXED_ARRAY( _ftype, _fname, _fcount, _fmax ) \
+ { t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fcount), \
+ 0 }
+
+#define Z1_FIELD_NUM_ARRAY2( _ftype, _fname, _fmax ) \
+ { t1_field_integer, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ 0, 0 }
+
+#define Z1_FIELD_FIXED_ARRAY2( _ftype, _fname, _fmax ) \
+ { t1_field_fixed, \
+ (FT_UInt)(char*)&Z1_FIELD_REF(_ftype,_fname), \
+ sizeof(Z1_FIELD_REF(_ftype,_fname)[0]), \
+ _fmax, \
+ 0, 0 }
+
+
+
+/*************************************************************************
+ *
+ * <Struct> Z1_Table
+ *
+ * <Description>
+ * A Z1_Table is a simple object used to store an array of objects
+ * in a single memory block.
+ *
+ * <Fields>
+ * block :: address in memory of the growheap's block. This
+ * can change between two object adds, due to the use
+ * of 'realloc'.
+ *
+ * cursor :: current top of the grow heap within its block
+ *
+ * capacity :: current size of the heap block. Increments by 1 Kb
+ *
+ * init :: boolean. set when the table has been initialized
+ * (the table user should set this field)
+ *
+ * max_elems :: maximum number of elements in table
+ * num_elems :: current number of elements in table
+ *
+ * elements :: table of element addresses within the block
+ * lengths :: table of element sizes within the block
+ *
+ * memory :: memory object used for memory operations (alloc/realloc)
+ */
+
+ typedef struct Z1_Table_
+ {
+ FT_Byte* block; /* current memory block */
+ FT_Int cursor; /* current cursor in memory block */
+ FT_Int capacity; /* current size of memory block */
+ FT_Long init;
+
+ FT_Int max_elems;
+ FT_Int num_elems;
+ FT_Byte** elements; /* addresses of table elements */
+ FT_Int* lengths; /* lengths of table elements */
+
+ FT_Memory memory;
+
+ } Z1_Table;
+
+
+/*************************************************************************
+ *
+ * <Struct> Z1_Parser
+ *
+ * <Description>
+ * A Z1_Parser is an object used to parse a Type 1 fonts very
+ * quickly.
+ *
+ * <Fields>
+ * stream :: current input stream
+ * memory :: current memory object
+ *
+ * base_dict :: pointer to top-level dictionary
+ * base_len :: length in bytes of top dict
+ *
+ * private_dict :: pointer to private dictionary
+ * private_len :: length in bytes of private dict
+ *
+ * in_pfb :: boolean. Indicates that we're in a .pfb file
+ * in_memory :: boolean. Indicates a memory-based stream
+ * single_block :: boolean. Indicates that the private dict
+ * is stored in lieu of the base dict
+ *
+ * cursor :: current parser cursor
+ * limit :: current parser limit (first byte after current
+ * dictionary).
+ *
+ * error :: current parsing error
+ */
+ typedef struct Z1_Parser_
+ {
+ FT_Stream stream;
+ FT_Memory memory;
+
+ FT_Byte* base_dict;
+ FT_Int base_len;
+
+ FT_Byte* private_dict;
+ FT_Int private_len;
+
+ FT_Byte in_pfb;
+ FT_Byte in_memory;
+ FT_Byte single_block;
+
+ FT_Byte* cursor;
+ FT_Byte* limit;
+ FT_Error error;
+
+ } Z1_Parser;
+
+
+ LOCAL_DEF
+ FT_Error Z1_New_Table( Z1_Table* table,
+ FT_Int count,
+ FT_Memory memory );
+
+
+ LOCAL_DEF
+ FT_Error Z1_Add_Table( Z1_Table* table,
+ FT_Int index,
+ void* object,
+ FT_Int length );
+
+#if 0
+ LOCAL_DEF
+ void Z1_Done_Table( Z1_Table* table );
+#endif
+
+ LOCAL_DEF
+ void Z1_Release_Table( Z1_Table* table );
+
+ LOCAL_DEF
+ FT_Long Z1_ToInt ( Z1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Long Z1_ToFixed( Z1_Parser* parser, FT_Int power_ten );
+
+ LOCAL_DEF
+ FT_Int Z1_ToCoordArray( Z1_Parser* parser,
+ FT_Int max_coords,
+ FT_Short* coords );
+
+ LOCAL_DEF
+ FT_Int Z1_ToFixedArray( Z1_Parser* parser,
+ FT_Int max_values,
+ FT_Fixed* values,
+ FT_Int power_ten );
+
+#if 0
+ LOCAL_DEF
+ FT_String* Z1_ToString( Z1_Parser* parser );
+
+ LOCAL_DEF
+ FT_Bool Z1_ToBool( Z1_Parser* parser );
+#endif
+
+
+
+
+
+
+ LOCAL_DEF
+ void Z1_Skip_Spaces( Z1_Parser* parser );
+
+ LOCAL_DEF
+ void Z1_ToToken( Z1_Parser* parser,
+ Z1_Token_Rec* token );
+
+ LOCAL_FUNC
+ void Z1_ToTokenArray( Z1_Parser* parser,
+ Z1_Token_Rec* tokens,
+ FT_UInt max_tokens,
+ FT_Int* pnum_tokens );
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Field( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+ LOCAL_DEF
+ FT_Error Z1_Load_Field_Table( Z1_Parser* parser,
+ const Z1_Field_Rec* field,
+ void** objects,
+ FT_UInt max_objects,
+ FT_ULong* pflags );
+
+
+ LOCAL_DEF
+ FT_Error Z1_New_Parser( Z1_Parser* parser,
+ FT_Stream stream,
+ FT_Memory memory );
+
+ LOCAL_DEF
+ FT_Error Z1_Get_Private_Dict( Z1_Parser* parser );
+
+ LOCAL_DEF
+ void Z1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed );
+
+ LOCAL_DEF
+ void Z1_Done_Parser( Z1_Parser* parser );
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1PARSE_H */
+
+
+/* END */
+
--- /dev/null
+++ b/src/type1z/z1tokens.h
@@ -1,0 +1,125 @@
+/*******************************************************************
+ *
+ * t1tokens.h
+ *
+ * Type 1 tokens definition
+ *
+ * Copyright 2000 David Turner, Robert Wilhelm and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ * This file only contains macros that are expanded when compiling
+ * the "t1load.c" source file.
+ *
+ ******************************************************************/
+
+#undef T1TYPE
+#define T1TYPE T1_FontInfo
+
+ Z1_FONTINFO_STRING( "version", version )
+ Z1_FONTINFO_STRING( "Notice", notice )
+ Z1_FONTINFO_STRING( "FullName", full_name )
+ Z1_FONTINFO_STRING( "FamilyName", family_name )
+ Z1_FONTINFO_STRING( "Weight", weight )
+
+ Z1_FONTINFO_NUM( "ItalicAngle", italic_angle )
+ Z1_FONTINFO_BOOL( "isFixedPitch", is_fixed_pitch )
+ Z1_FONTINFO_NUM( "UnderlinePosition", underline_position )
+ Z1_FONTINFO_NUM( "UnderlineThickness", underline_thickness )
+
+#undef T1TYPE
+#define T1TYPE T1_Private
+
+ Z1_PRIVATE_NUM ( "UniqueID", unique_id )
+ Z1_PRIVATE_NUM ( "lenIV", lenIV )
+ Z1_PRIVATE_NUM ( "LanguageGroup", language_group )
+ Z1_PRIVATE_NUM ( "password", password )
+
+ Z1_PRIVATE_FIXED( "BlueScale", blue_scale )
+ Z1_PRIVATE_NUM ( "BlueShift", blue_shift )
+ Z1_PRIVATE_NUM ( "BlueFuzz", blue_fuzz )
+
+ Z1_PRIVATE_NUM_TABLE( "BlueValues", blue_values, 14, num_blue_values )
+ Z1_PRIVATE_NUM_TABLE( "OtherBlues", other_blues, 10, num_other_blues )
+ Z1_PRIVATE_NUM_TABLE( "FamilyBlues", family_blues, 14, num_family_blues )
+ Z1_PRIVATE_NUM_TABLE( "FamilyOtherBlues", family_other_blues, 10, num_family_other_blues )
+
+ Z1_PRIVATE_NUM_TABLE2( "StdHW", standard_width, 1 )
+ Z1_PRIVATE_NUM_TABLE2( "StdVW", standard_height, 1 )
+ Z1_PRIVATE_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+ Z1_PRIVATE_NUM_TABLE ( "StemSnapH", snap_widths, 12, num_snap_widths )
+ Z1_PRIVATE_NUM_TABLE ( "StemSnapV", snap_heights, 12, num_snap_heights )
+
+#undef T1TYPE
+#define T1TYPE T1_Font
+
+ Z1_TOPDICT_NUM( "PaintType", paint_type )
+ Z1_TOPDICT_NUM( "FontType", font_type )
+ Z1_TOPDICT_NUM( "StrokeWidth", stroke_width )
+
+#if 0
+ /* define the font info dictionary parsing callbacks */
+#undef FACE
+#define FACE (face->type1.font_info)
+
+ PARSE_STRING("version",version)
+ PARSE_STRING("Notice",notice)
+ PARSE_STRING("FullName",full_name)
+ PARSE_STRING("FamilyName",family_name)
+ PARSE_STRING("Weight",weight)
+
+ PARSE_INT("ItalicAngle",italic_angle)
+ PARSE_BOOL("isFixedPitch",is_fixed_pitch)
+ PARSE_NUM("UnderlinePosition",underline_position,FT_Short)
+ PARSE_NUM("UnderlineThickness",underline_thickness,FT_UShort)
+
+ /* define the private dict parsing callbacks */
+
+#undef FACE
+#define FACE (face->type1.private_dict)
+
+ PARSE_INT("UniqueID",unique_id)
+ PARSE_INT("lenIV",lenIV)
+
+ PARSE_COORDS( "BlueValues", num_blues, 14, blue_values)
+ PARSE_COORDS( "OtherBlues", num_other_blues, 10, other_blues)
+
+ PARSE_COORDS( "FamilyBlues", num_family_blues, 14, family_blues)
+ PARSE_COORDS( "FamilyOtherBlues", num_family_other_blues, 10, family_other_blues)
+
+ PARSE_FIXED( "BlueScale", blue_scale)
+ PARSE_INT( "BlueShift", blue_shift)
+
+ PARSE_INT( "BlueFuzz", blue_fuzz)
+
+ PARSE_COORDS2( "StdHW", 1, standard_width )
+ PARSE_COORDS2( "StdVW", 1, standard_height )
+
+ PARSE_COORDS( "StemSnapH", num_snap_widths, 12, stem_snap_widths )
+ PARSE_COORDS( "StemSnapV", num_snap_heights, 12, stem_snap_heights )
+
+ PARSE_INT( "LanguageGroup", language_group )
+ PARSE_INT( "password", password )
+ PARSE_COORDS2( "MinFeature", 2, min_feature )
+
+ /* define the top-level dictionary parsing callbacks */
+
+#undef FACE
+#define FACE (face->type1)
+
+
+/* PARSE_STRING( "FontName", font_name ) -- handled by special routine */
+ PARSE_NUM( "PaintType", paint_type, FT_Byte )
+ PARSE_NUM( "FontType", font_type, FT_Byte )
+ PARSE_FIXEDS2( "FontMatrix", 4, font_matrix )
+/* PARSE_COORDS2( "FontBBox", 4, font_bbox ) -- handled by special func */
+ PARSE_INT( "StrokeWidth", stroke_width )
+
+#undef FACE
+#endif
+