fixed divide by zero bug

added CFF/OpenType driver source (not working for now)
This commit is contained in:
David Turner 2000-05-29 20:55:13 +00:00
parent a519b3b7a3
commit 4f99c3c423
17 changed files with 3533 additions and 8 deletions

View File

@ -1,5 +1,14 @@
LATEST_CHANGES
- fixed potential "divide by zero" bugs in ftcalc.c.. my god..
- added source code for the OpenType/CFF driver (still incomplete though..)
- modified the SFNT driver slightly to perform more robust header
checks in TT_Load_SFNT_Header. This prevents certain font files
(e.g. some Type 1 Multiple Masters) from being incorrectly "recognized"
as TrueType font files..
- moved a lot of stuff from the TrueType driver to the SFNT module,
this allows greater code re-use between font drivers (e.g. TrueType,
OpenType, Compact-TrueType, etc..)

View File

@ -132,13 +132,13 @@
{
FT_Int s;
s = 1;
if ( a < 0 ) { a = -a; s = -s; }
if ( b < 0 ) { b = -b; s = -s; }
if ( c < 0 ) { c = -c; s = -s; }
return s * ( ( (FT_Int64)a * b + ( c >> 1 ) ) / c );
return s * ( c > 0 ? ( ( (FT_Int64)a * b + ( c >> 1 ) ) / c )
: 0x7FFFFFFF );
}
@ -344,21 +344,22 @@
s ^= b; b = ABS( b );
s ^= c; c = ABS( c );
if ( a <= 46340 && b <= 46340 && c <= 176095L )
if ( a <= 46340 && b <= 46340 && c <= 176095L && c > 0)
{
a = ( a*b + (c >> 1) ) / c;
a = a*b + (c >> 1) ) / c;
}
else
else if (c > 0)
{
FT_Int64 temp, temp2;
FT_MulTo64( a, b, &temp );
temp2.hi = (FT_Int32)(c >> 31);
temp2.lo = (FT_Word32)(c / 2);
FT_Add64( &temp, &temp2, &temp );
a = FT_Div64by32( &temp, c );
}
else
a = 0x7FFFFFFF;
return ( s < 0 ) ? -a : a;
}
@ -614,7 +615,6 @@
FT_Int32 s;
FT_Word32 q, r, i, lo;
s = x->hi;
if ( s < 0 )
{
@ -626,7 +626,9 @@
/* Shortcut */
if ( x->hi == 0 )
{
q = x->lo / y;
if (y > 0) q = x->lo / y;
else q = 0x7FFFFFFF;
return ( s < 0 ) ? -(FT_Int32)q : (FT_Int32)q;
}

49
src/cff/cff.c Normal file
View File

@ -0,0 +1,49 @@
/***************************************************************************/
/* */
/* cff.c */
/* */
/* FreeType OpenType driver component (body only). */
/* */
/* 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. */
/* */
/***************************************************************************/
/*************************************************************************/
/* */
/* This file is used to compile the FreeType TrueType font driver. It */
/* relies on all components included in the `base' layer (see the file */
/* `ftbase.c'). The source code is located in `freetype/ttlib' and */
/* contains: */
/* */
/* - a driver interface */
/* - an object manager */
/* - a table loader */
/* - a glyph loader */
/* - a glyph hinter/bytecode interpreter */
/* - a charmap processor */
/* - an extension manager (only used for some tools) */
/* */
/* Note that the engine extensions found in `freetype/ttlib/extend' are */
/* reserved to specific tools and/or font servers; they're not part of */
/* the `core' TrueType driver, even though they are separately linkable */
/* to it. */
/* */
/*************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include <t2driver.c> /* driver interface */
#include <t2parse.c> /* token parser */
#include <t2load.c> /* tables loader */
#include <t2objs.c> /* object management */
/* END */

7
src/cff/module.mk Normal file
View File

@ -0,0 +1,7 @@
make_module_list: add_cff_driver
add_cff_driver:
$(OPEN_DRIVER)cff_driver_interface$(CLOSE_DRIVER)
$(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
# EOF

112
src/cff/rules.mk Normal file
View File

@ -0,0 +1,112 @@
#
# FreeType 2 OpenType/CFF driver configuration rules
#
# 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.
# Include the rules defined for the SFNT driver, which is heavily used
# by the TrueType one.
#
include $(SRC_)sfnt/rules.mk
# OpenType driver directory
#
T2_DIR := $(SRC_)cff
T2_DIR_ := $(T2_DIR)$(SEP)
# location of all extensions to the driver, if any
#
T2_EXT_DIR := $(T2_DIR_)extend
T2_EXT_DIR_ := $(T2_EXT_DIR)$(SEP)
# additional include flags used when compiling the driver
#
T2_INCLUDE := $(SFNT_INCLUDE) $(T2_DIR) $(T2_EXT_DIR)
# compilation flags for the driver
#
T2_CFLAGS := $(T2_INCLUDE:%=$I%)
T2_COMPILE := $(FT_COMPILE) $(T2_CFLAGS)
# driver sources (i.e., C files)
#
T2_DRV_SRC := $(T2_DIR_)t2objs.c \
$(T2_DIR_)t2load.c \
$(T2_DIR_)t2gload.c \
$(T2_DIR_)t2parse.c \
$(T2_DIR_)t2driver.c
# driver headers
#
T2_DRV_H := $(SFNT_H) \
$(T2_DRV_SRC:%.c=%.h)
# default extensions headers
#
T2_EXT_H := $(T2_EXT_SRC:.c=.h)
# driver object(s)
#
# T2_DRV_OBJ_M is used during `debug' builds
# T2_DRV_OBJ_S is used during `release' builds
#
T2_DRV_OBJ_M := $(T2_DRV_SRC:$(T2_DIR_)%.c=$(OBJ_)%.$O)
T2_DRV_OBJ_S := $(OBJ_)cff.$O
# default extensions objects
#
T2_EXT_OBJ := $(T2_EXT_SRC:$(T2_EXT_DIR_)%.c=$(OBJ_)%.$O)
# driver source file(s)
#
T2_DRV_SRC_M := $(T2_DRV_SRC) $(SFNT_SRC)
T2_DRV_SRC_S := $(T2_DIR_)cff.c
# driver - single object
#
# the driver is recompiled if any of the header or source files is changed
# as well as any of the shared source files found in `shared/sfnt'
#
$(T2_DRV_OBJ_S): $(BASE_H) $(T2_DRV_H) $(T2_DRV_SRC) $(T2_DRV_SRC_S)
$(T2_COMPILE) $T$@ $(T2_DRV_SRC_S)
# driver - multiple objects
#
# All objects are recompiled if any of the header files is changed
#
$(OBJ_)t2%.$O: $(T2_DIR_)t2%.c $(BASE_H) $(T2_DRV_H)
$(T2_COMPILE) $T$@ $<
$(OBJ_)t2x%.$O: $(T2_EXT_DIR_)t2x%.c $(BASE_H) $(SFNT_H) $(T2_EXT_H)
$(T2_COMPILE) $T$@ $<
$(OBJ_)t2%.$O: $(SFNT_DIR_)t2%.c $(BASE_H) $(SFNT_H)
$(T2_COMPILE) $T$@ $<
# update main driver object lists
#
DRV_OBJS_S += $(T2_DRV_OBJ_S)
DRV_OBJS_M += $(T2_DRV_OBJ_M)
# EOF

444
src/cff/t2driver.c Normal file
View File

@ -0,0 +1,444 @@
/***************************************************************************/
/* */
/* t2driver.c */
/* */
/* OpenType font driver implementation (body). */
/* */
/* 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 <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/internal/sfnt.h>
#include <freetype/ttnameid.h>
#include <t2driver.h>
#include <t2gload.h>
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttdriver
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** F A C E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
#undef PAIR_TAG
#define PAIR_TAG( left, right ) ( ((TT_ULong)left << 16) | (TT_ULong)right )
/*************************************************************************/
/* */
/* <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
TT_Error Get_Kerning( TT_Face face,
TT_UInt left_glyph,
TT_UInt right_glyph,
TT_Vector* kerning )
{
TT_Kern_0_Pair* pair;
if ( !face )
return FT_Err_Invalid_Face_Handle;
kerning->x = 0;
kerning->y = 0;
if ( face->kern_pairs )
{
/* there are some kerning pairs in this font file! */
TT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph );
TT_Long left, right;
left = 0;
right = face->num_kern_pairs - 1;
while ( left <= right )
{
TT_Int middle = left + ((right-left) >> 1);
TT_ULong cur_pair;
pair = face->kern_pairs + middle;
cur_pair = PAIR_TAG( pair->left, pair->right );
if ( cur_pair == search_tag )
goto Found;
if ( cur_pair < search_tag )
left = middle+1;
else
right = middle-1;
}
}
Exit:
return FT_Err_Ok;
Found:
kerning->x = pair->value;
goto Exit;
}
#undef PAIR_TAG
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** S I Z E S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* Set_Char_Sizes */
/* */
/* <Description> */
/* A driver method used to reset a size's character sizes (horizontal */
/* and vertical) expressed in fractional points. */
/* */
/* <Input> */
/* char_width :: The character width expressed in 26.6 fractional */
/* points. */
/* char_height :: The character height expressed in 26.6 fractional */
/* points. */
/* */
/* <InOut> */
/* size :: A handle to the target size object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
static
TT_Error Set_Char_Sizes( T2_Size size,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
FT_UInt horz_resolution,
FT_UInt vert_resolution )
{
FT_Size_Metrics* metrics = &size->metrics;
T2_Face face = (T2_Face)size->face;
FT_Long dim_x, dim_y;
/* This bit flag, when set, indicates that the pixel size must be */
/* truncated to an integer. Nearly all TrueType fonts have this */
/* bit set, as hinting won't work really well otherwise. */
/* */
/* However, for those rare fonts who do not set it, we override */
/* the default computations performed by the base layer. I really */
/* don't know if this is useful, but hey, that's the spec :-) */
/* */
if ( (face->header.Flags & 8) == 0 )
{
/* Compute pixel sizes in 26.6 units */
dim_x = (char_width * horz_resolution) / 72;
dim_y = (char_height * vert_resolution) / 72;
metrics->x_scale = FT_DivFix( dim_x, face->root.units_per_EM );
metrics->y_scale = FT_DivFix( dim_y, face->root.units_per_EM );
metrics->x_ppem = (TT_UShort)(dim_x >> 6);
metrics->y_ppem = (TT_UShort)(dim_y >> 6);
}
return T2_Reset_Size( size );
}
/*************************************************************************/
/* */
/* <Function> */
/* Set_Pixel_Sizes */
/* */
/* <Description> */
/* A driver method used to reset a size's character sizes (horizontal */
/* and vertical) expressed in integer pixels. */
/* */
/* <Input> */
/* pixel_width :: The character width expressed in integer pixels. */
/* */
/* pixel_height :: The character height expressed in integer pixels. */
/* */
/* <InOut> */
/* size :: A handle to the target size object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success */
/* */
static
FT_Error Set_Pixel_Sizes( T2_Size size,
FT_UInt pixel_width,
FT_UInt pixel_height )
{
UNUSED(pixel_width);
UNUSED(pixel_height);
return T2_Reset_Size( size );
}
/*************************************************************************/
/* */
/* <Function> */
/* Load_Glyph */
/* */
/* <Description> */
/* A driver method used to load a glyph within a given glyph slot. */
/* */
/* <Input> */
/* slot :: A handle to the target slot object where the glyph */
/* will be loaded. */
/* */
/* size :: A handle to the source face size at which the glyph */
/* must be scaled/loaded/etc. */
/* */
/* glyph_index :: The index of the glyph in the font file. */
/* */
/* load_flags :: A flag indicating what to load for this glyph. The */
/* FTLOAD_??? constants can be used to control the */
/* glyph loading process (e.g., whether the outline */
/* should be scaled, whether to load bitmaps or not, */
/* whether to hint the outline, etc). */
/* <Output> */
/* result :: A set of bit flags indicating the type of data that */
/* was loaded in the glyph slot (outline, bitmap, */
/* pixmap, etc). */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
static
FT_Error Load_Glyph( T2_GlyphSlot slot,
T2_Size size,
FT_UShort glyph_index,
FT_UInt load_flags )
{
FT_Error error;
if ( !slot )
return FT_Err_Invalid_Handle;
/* check that we want a scaled outline or bitmap */
if ( !size )
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
if ( load_flags & FT_LOAD_NO_SCALE )
size = NULL;
/* reset the size object if necessary */
if ( size )
{
/* these two object must have the same parent */
if ( size->face != slot->face )
return FT_Err_Invalid_Face_Handle;
}
/* now load the glyph outline if necessary */
#if 1 /* XXXX: TODO */
error = FT_Err_Unimplemented_Feature;
#else
error = T2_Load_Glyph( size, slot, glyph_index, load_flags );
#endif
/* force drop-out mode to 2 - irrelevant now */
/* slot->outline.dropout_mode = 2; */
return error;
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
/**** C H A R A C T E R M A P P I N G S ****/
/**** ****/
/**** ****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* <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( TT_CharMap charmap,
FT_Long charcode )
{
FT_Error error;
T2_Face face;
TT_CMapTable* cmap;
cmap = &charmap->cmap;
face = (T2_Face)charmap->root.face;
/* Load table if needed */
if ( !cmap->loaded )
{
SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt;
error = sfnt->load_charmap( face, cmap, face->root.stream );
if (error) return error;
cmap->loaded = TRUE;
}
return (cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 );
}
static
FTDriver_Interface t2_get_interface( T2_Driver driver, const char* interface )
{
FT_Driver sfntd = FT_Get_Driver( driver->root.library, "sfnt" );
SFNT_Interface* sfnt;
/* only return the default interface from the SFNT module */
if (sfntd)
{
sfnt = (SFNT_Interface*)(sfntd->interface.format_interface);
if (sfnt)
return sfnt->get_interface( (FT_Driver)driver, interface );
}
return 0;
}
/* The FT_DriverInterface structure is defined in ftdriver.h. */
const FT_DriverInterface cff_driver_interface =
{
sizeof ( T2_DriverRec ),
sizeof ( TT_FaceRec ),
sizeof ( FT_SizeRec ),
sizeof ( FT_GlyphSlotRec ),
"cff", /* driver name */
100, /* driver version == 1.0 */
200, /* driver requires FreeType 2.0 or above */
(void*)0,
(FTDriver_initDriver) T2_Init_Driver,
(FTDriver_doneDriver) T2_Done_Driver,
(FTDriver_getInterface) t2_get_interface,
(FTDriver_initFace) T2_Init_Face,
(FTDriver_doneFace) T2_Done_Face,
(FTDriver_getKerning) Get_Kerning,
(FTDriver_initSize) T2_Init_Size,
(FTDriver_doneSize) T2_Done_Size,
(FTDriver_setCharSizes) Set_Char_Sizes,
(FTDriver_setPixelSizes) Set_Pixel_Sizes,
(FTDriver_initGlyphSlot) T2_Init_GlyphSlot,
(FTDriver_doneGlyphSlot) T2_Done_GlyphSlot,
(FTDriver_loadGlyph) Load_Glyph,
(FTDriver_getCharIndex) Get_Char_Index,
};
/*************************************************************************/
/* */
/* <Function> */
/* getDriverInterface */
/* */
/* <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> */
/* The address of the TrueType's driver generic interface. The */
/* format-specific interface can then be retrieved through the method */
/* interface->get_format_interface. */
/* */
#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
EXPORT_FUNC(FT_DriverInterface*) getDriverInterface( void )
{
return &cff_driver_interface;
}
#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */
/* END */

34
src/cff/t2driver.h Normal file
View File

@ -0,0 +1,34 @@
/***************************************************************************/
/* */
/* t2driver.h */
/* */
/* High-level OpenType driver interface (specification). */
/* */
/* 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 T2DRIVER_H
#define T2DRIVER_H
#include <freetype/internal/ftdriver.h>
#include <freetype/ttnameid.h>
#include <t2objs.h>
#include <t2errors.h>
FT_EXPORT_VAR(const FT_DriverInterface) cff_driver_interface;
#endif /* T2DRIVER_H */
/* END */

126
src/cff/t2errors.h Normal file
View File

@ -0,0 +1,126 @@
/***************************************************************************/
/* */
/* t2errors.h */
/* */
/* OpenType error ID definitions (specification only). */
/* */
/* 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 T2ERRORS_H
#define T2ERRORS_H
/*************************************************************************/
/* */
/* Error codes declaration */
/* */
/* The error codes are grouped in `classes' used to indicate the `level' */
/* at which the error happened. The class is given by an error code's */
/* high byte. */
/* */
/*************************************************************************/
/* Success is always 0. */
#define T2_Err_Ok FT_Err_Ok
/* High level API errors. */
#define T2_Err_Invalid_File_Format FT_Err_Invalid_File_Format
#define T2_Err_Invalid_Argument FT_Err_Invalid_Argument
#define T2_Err_Invalid_Driver_Handle FT_Err_Invalid_Driver_Handle
#define T2_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
#define T2_Err_Invalid_Instance_Handle FT_Err_Invalid_Size_Handle
#define T2_Err_Invalid_Glyph_Handle FT_Err_Invalid_Slot_Handle
#define T2_Err_Invalid_CharMap_Handle FT_Err_Invalid_CharMap_Handle
#define T2_Err_Invalid_Glyph_Index FT_Err_Invalid_Glyph_Index
#define T2_Err_Unimplemented_Feature FT_Err_Unimplemented_Feature
#define T2_Err_Unavailable_Outline FT_Err_Unavailable_Outline
#define T2_Err_Unavailable_Bitmap FT_Err_Unavailable_Bitmap
#define T2_Err_Unavailable_Pixmap FT_Err_Unavailable_Pixmap
#define T2_Err_File_Is_Not_Collection FT_Err_File_Is_Not_Collection
#define T2_Err_Invalid_Engine FT_Err_Invalid_Driver_Handle
/* Internal errors. */
#define T2_Err_Out_Of_Memory FT_Err_Out_Of_Memory
#define T2_Err_Unlisted_Object FT_Err_Unlisted_Object
/* General glyph outline errors. */
#define T2_Err_Too_Many_Points FT_Err_Too_Many_Points
#define T2_Err_Too_Many_Contours FT_Err_Too_Many_Contours
#define T2_Err_Too_Many_Ins FT_Err_Too_Many_Hints
#define T2_Err_Invalid_Composite FT_Err_Invalid_Composite
/* Bytecode interpreter error codes. */
/* These error codes are produced by the TrueType */
/* bytecode interpreter. They usually indicate a */
/* broken font file, a broken glyph within a font */
/* file, or a bug in the interpreter! */
#define T2_Err_Invalid_Opcode 0x400
#define T2_Err_Too_Few_Arguments 0x401
#define T2_Err_Stack_Overflow 0x402
#define T2_Err_Code_Overflow 0x403
#define T2_Err_Bad_Argument 0x404
#define T2_Err_Divide_By_Zero 0x405
#define T2_Err_Storage_Overflow 0x406
#define T2_Err_Cvt_Overflow 0x407
#define T2_Err_Invalid_Reference 0x408
#define T2_Err_Invalid_Distance 0x409
#define T2_Err_Interpolate_Twilight 0x40A
#define T2_Err_Debug_OpCode 0x40B
#define T2_Err_ENDF_In_Exec_Stream 0x40C
#define T2_Err_Out_Of_CodeRanges 0x40D
#define T2_Err_Nested_DEFS 0x40E
#define T2_Err_Invalid_CodeRange 0x40F
#define T2_Err_Invalid_Displacement 0x410
#define T2_Err_Execution_Too_Long 0x411
#define T2_Err_Too_Many_Instruction_Defs 0x412
#define T2_Err_Too_Many_Function_Defs 0x412
/* Other TrueType specific error codes. */
#define T2_Err_Table_Missing 0x420
#define T2_Err_Too_Many_Extensions 0x421
#define T2_Err_Extensions_Unsupported 0x422
#define T2_Err_Invalid_Extension_Id 0x423
#define T2_Err_No_Vertical_Data 0x424
#define T2_Err_Max_Profile_Missing 0x430
#define T2_Err_Header_Table_Missing 0x431
#define T2_Err_Horiz_Header_Missing 0x432
#define T2_Err_Locations_Missing 0x433
#define T2_Err_Name_Table_Missing 0x434
#define T2_Err_CMap_Table_Missing 0x435
#define T2_Err_Hmtx_Table_Missing 0x436
#define T2_Err_OS2_Table_Missing 0x437
#define T2_Err_Post_Table_Missing 0x438
#define T2_Err_Invalid_Horiz_Metrics 0x440
#define T2_Err_Invalid_CharMap_Format 0x441
#define T2_Err_Invalid_PPem 0x442
#define T2_Err_Invalid_Vert_Metrics 0x443
#define T2_Err_Could_Not_Find_Context 0x450
#endif /* FTERRID_H */
/* END */

1177
src/cff/t2gload.c Normal file

File diff suppressed because it is too large Load Diff

140
src/cff/t2gload.h Normal file
View File

@ -0,0 +1,140 @@
/***************************************************************************/
/* */
/* t2gload.h */
/* */
/* OpenType Glyph Loader (specification). */
/* */
/* 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 T2GLOAD_H
#define T2GLOAD_H
#include <t2objs.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct T2_Loader_
{
T2_Face face;
T2_Size size;
T2_GlyphSlot glyph;
FT_ULong load_flags;
FT_UInt glyph_index;
FT_Stream stream;
FT_Int byte_len;
FT_Int left_points;
FT_Int left_contours;
FT_BBox bbox;
FT_Int left_bearing;
FT_Int advance;
FT_Bool preserve_pps;
FT_Vector pp1;
FT_Vector pp2;
FT_ULong glyf_offset;
/* the zone where we load our glyphs */
FT_GlyphZone base;
FT_GlyphZone zone;
} T2_Loader;
#if 0
/*************************************************************************/
/* */
/* <Function> */
/* T2_Get_Metrics */
/* */
/* <Description> */
/* Returns the horizontal or vertical metrics in font units for a */
/* given glyph. The metrics are the left side bearing (resp. top */
/* side bearing) and advance width (resp. advance height). */
/* */
/* <Input> */
/* header :: A pointer to either the horizontal or vertical metrics */
/* structure. */
/* */
/* index :: The glyph index. */
/* */
/* <Output> */
/* bearing :: The bearing, either left side or top side. */
/* */
/* advance :: The advance width resp. advance height. */
/* */
/* <Note> */
/* This function will much probably move to another component in the */
/* near future, but I haven't decided which yet. */
/* */
LOCAL_DEF
void T2_Get_Metrics( TT_HoriHeader* header,
FT_UInt index,
FT_Short* bearing,
FT_UShort* advance );
/*************************************************************************/
/* */
/* <Function> */
/* T2_Load_Glyph */
/* */
/* <Description> */
/* A function used to load a single glyph within a given glyph slot, */
/* for a given size. */
/* */
/* <Input> */
/* glyph :: A handle to a target slot object where the glyph */
/* will be loaded. */
/* */
/* size :: A handle to the source face size at which the glyph */
/* must be scaled/loaded. */
/* */
/* glyph_index :: The index of the glyph in the font file. */
/* */
/* load_flags :: A flag indicating what to load for this glyph. The */
/* FT_LOAD_XXX constants can be used to control the */
/* glyph loading process (e.g., whether the outline */
/* should be scaled, whether to load bitmaps or not, */
/* whether to hint the outline, etc). */
/* <Output> */
/* result :: A set of bit flags indicating the type of data that */
/* was loaded in the glyph slot (outline or bitmap, */
/* etc). */
/* */
/* You can set this field to 0 if you don't want this */
/* information. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error T2_Load_Glyph( T2_Size size,
T2_GlyphSlot glyph,
FT_UShort glyph_index,
FT_UInt load_flags );
#endif
#ifdef __cplusplus
}
#endif
#endif /* T2GLOAD_H */
/* END */

292
src/cff/t2load.c Normal file
View File

@ -0,0 +1,292 @@
/***************************************************************************/
/* */
/* t2load.h */
/* */
/* TrueType glyph data/program tables loader (body). */
/* */
/* 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 <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftstream.h>
#include <freetype/fterrors.h>
#include <freetype/tttags.h>
#include <t2load.h>
#include <t2parse.h>
#include <t2errors.h>
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttload
/* read a CFF offset from memory */
LOCAL_FUNC
FT_ULong T2_Get_Offset( FT_Byte* p,
FT_Byte off_size )
{
FT_ULong result;
for ( result = 0; off_size > 0; off_size-- )
result = (result <<= 8) | *p++;
return result;
}
#if 0
/* read a CFF offset from a stream */
LOCAL_FUNC
FT_ULong T2_Read_Offset( FT_Byte off_size,
FT_Stream stream )
{
FT_Byte bytes[4];
FT_Byte* p;
FT_ULong result;
if (off_size > 4)
off_size = 4;
/* first of all, read or access the bytes - this should really go */
/* in "src/base/ftstream.c", but there are great chances that it will */
/* never be used elsewhere, so.. */
if (stream->read)
{
p = bytes;
if ( stream->read( stream, stream->pos, (char*)bytes, off_size ) != off_size )
goto Fail;
}
else
{
p = (FT_Byte*)stream->base + stream->pos;
if (p+off_size-1 >= (FT_Byte*)stream->limit)
goto Fail;
}
result = 0;
while (off_size > 0)
{
result = (result <<= 8) | *p++;
off_size--;
}
stream->pos += off_size;
return result;
Fail:
FT_ERROR(( "T2_Read_Offset:" ));
FT_ERROR(( " invalid i/o, pos = 0x%lx, size = 0x%lx",
stream->pos, stream->size ));
return 0;
}
#endif
/* return the memory address of a CFF index's element, when the index */
/* is already loaded in memory.. */
LOCAL_FUNC
FT_Error T2_Access_Element( CFF_Index* cff_index,
FT_UInt element,
FT_Byte* *pbytes,
FT_ULong *pbyte_len )
{
FT_Error error;
if (cff_index && cff_index->bytes && element < (FT_UInt)cff_index->count)
{
FT_ULong off1, off2;
FT_Byte offsize = cff_index->off_size;
FT_Byte* p = cff_index->bytes + 3 + element*offsize;
FT_Byte* limit = cff_index->bytes + cff_index->data_offset;
/* read element offset */
off1 = T2_Get_Offset(p,offsize);
/* a value of 0 indicates no object !! */
if (off1)
{
/* compute offset of next element - skip empty elements */
do
{
p += offsize;
off2 = T2_Get_Offset(p,offsize);
}
while (off2 == 0 && p < limit);
if (p >= limit)
off1 = 0;
}
*pbytes = 0;
*pbyte_len = 0;
if (off1)
{
*pbytes = cff_index->bytes + cff_index->data_offset + off1 - 1;
*pbyte_len = off2 - off1;
}
error = 0;
}
else
error = FT_Err_Invalid_Argument;
return error;
}
LOCAL_FUNC
LOCAL_FUNC
FT_Error T2_Read_CFF_Index( CFF_Index* index,
FT_Stream stream )
{
FT_Error error;
FT_ULong data_size;
MEM_Set( index, 0, sizeof(*index) );
index->file_offset = FILE_Pos();
if ( !READ_UShort( index->count ) &&
index->count > 0 )
{
FT_Byte* p;
FT_Byte offsize;
/* there is at least one element, read the offset size */
/* then access the offset table to compute the index's total size */
if ( READ_Byte( offsize ) )
goto Exit;
index->off_size = offsize;
index->data_offset = ((FT_Long)index->count + 1)*offsize;
if (ACCESS_Frame( index->data_offset ))
goto Exit;
/* now read element offset limit */
p = (FT_Byte*)stream->cursor + index->data_offset - offsize;
data_size = T2_Get_Offset( p, offsize );
FORGET_Frame();
index->data_offset += 3;
index->total_size = index->data_offset + data_size;
/* skip the data */
(void)FILE_Skip( data_size );
}
Exit:
return error;
}
LOCAL_FUNC
FT_Error T2_Load_CFF_Index( CFF_Index* index,
FT_Stream stream )
{
FT_Error error;
/* we begin by reading the index's data */
error = T2_Read_CFF_Index( index, stream );
if (!error && index->total_size > 0)
{
/* OK, read it from the file */
if ( FILE_Seek( index->file_offset ) ||
EXTRACT_Frame( index->total_size, index->bytes ) )
goto Exit;
/* done !! */
}
Exit:
return error;
}
LOCAL_FUNC
void T2_Done_CFF_Index( CFF_Index* index,
FT_Stream stream )
{
if (index->bytes)
RELEASE_Frame( index->bytes );
MEM_Set( index, 0, sizeof(*index) );
}
LOCAL_FUNC
FT_Error T2_Load_CFF_Font( FT_Stream stream,
CFF_Font* font )
{
static const FT_Frame_Field cff_header_fields[] = {
FT_FRAME_START(4),
FT_FRAME_BYTE( CFF_Font, version_major ),
FT_FRAME_BYTE( CFF_Font, version_minor ),
FT_FRAME_BYTE( CFF_Font, header_size ),
FT_FRAME_BYTE( CFF_Font, absolute_offsize ),
FT_FRAME_END };
FT_Error error;
MEM_Set( font, 0, sizeof(*font) );
font->stream = stream;
font->memory = stream->memory;
/* read CFF font header */
if ( READ_Fields( cff_header_fields, font ) )
goto Exit;
/* check format */
if ( font->version_major != 1 ||
font->header_size < 4 ||
font->absolute_offsize > 4 )
{
FT_ERROR(( "incorrect CFF font header !!\n" ));
error = FT_Err_Unknown_File_Format;
goto Exit;
}
/* skip the rest of the header */
(void)FILE_Skip( font->header_size - 4 );
/* read the name, top dict, strong and global subrs index */
error = T2_Load_CFF_Index( &font->name_index, stream ) ||
T2_Load_CFF_Index( &font->top_dict_index, stream ) ||
T2_Read_CFF_Index( &font->string_index, stream ) ||
T2_Load_CFF_Index( &font->global_subrs_index, stream );
if (error) goto Exit;
/* well, we don't really forget the "disable" fonts.. */
font->num_faces = font->name_index.count;
Exit:
return error;
}
LOCAL_FUNC
void T2_Done_CFF_Font( CFF_Font* font )
{
FT_Stream stream = font->stream;
T2_Done_CFF_Index( &font->global_subrs_index, stream );
T2_Done_CFF_Index( &font->string_index, stream );
T2_Done_CFF_Index( &font->top_dict_index, stream );
T2_Done_CFF_Index( &font->name_index, stream );
}
/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
/***** *****/
/***** TYPE 2 TABLES DECODING.. *****/
/***** *****/
/***********************************************************************/
/***********************************************************************/
/***********************************************************************/
/* END */

36
src/cff/t2load.h Normal file
View File

@ -0,0 +1,36 @@
/***************************************************************************/
/* */
/* t2load.h */
/* */
/* OpenType glyph data/program tables loader (specification). */
/* */
/* 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 T2LOAD_H
#define T2LOAD_H
#include <freetype/internal/t2types.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* T2LOAD_H */
/* END */

333
src/cff/t2objs.c Normal file
View File

@ -0,0 +1,333 @@
/***************************************************************************/
/* */
/* ttobjs.c */
/* */
/* Objects manager (body). */
/* */
/* 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 <freetype/internal/ftdebug.h>
#include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftstream.h>
#include <freetype/ttnameid.h>
#include <freetype/tttags.h>
#include <freetype/internal/sfnt.h>
#include <freetype/internal/psnames.h>
#include <t2objs.h>
#include <t2load.h>
#include <t2errors.h>
/* required by tracing mode */
#undef FT_COMPONENT
#define FT_COMPONENT trace_ttobjs
/*************************************************************************/
/* */
/* GLYPH ZONE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* T2_Init_Face */
/* */
/* <Description> */
/* Initializes a given TrueType face object. */
/* */
/* <Input> */
/* resource :: The source font resource. */
/* face_index :: The index of the font face in the resource. */
/* face :: The newly built face object. */
/* */
/* <Return> */
/* TrueType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error T2_Init_Face( FT_Stream stream,
T2_Face face,
FT_Int face_index,
FT_Int num_params,
FT_Parameter* params )
{
TT_Error error;
FT_Driver sfnt_driver;
SFNT_Interface* sfnt;
sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" );
if (!sfnt_driver) goto Bad_Format;
sfnt = (SFNT_Interface*)(sfnt_driver->interface.format_interface);
if (!sfnt) goto Bad_Format;
/* create input stream from resource */
if ( FILE_Seek(0) )
goto Exit;
/* check that we have a valid TrueType file */
error = sfnt->init_face( stream, face, face_index, num_params, params );
if (error) goto Exit;
/* We must also be able to accept Mac/GX fonts, as well as OT ones */
if ( face->format_tag != 0x4f54544f ) /* OpenType/CFF font */
{
FT_TRACE2(( "[not a valid OpenType/CFF font]" ));
goto Bad_Format;
}
/* If we're performing a simple font format check, exit immediately */
if ( face_index < 0 )
return FT_Err_Ok;
/* Load font directory */
error = sfnt->load_face( stream, face, face_index, num_params, params );
if ( error ) goto Exit;
Exit:
return error;
Bad_Format:
error = FT_Err_Unknown_File_Format;
goto Exit;
}
/*************************************************************************/
/* */
/* <Function> */
/* T2_Done_Face */
/* */
/* <Description> */
/* Finalizes a given face object. */
/* */
/* <Input> */
/* face :: A pointer to the face object to destroy. */
/* */
LOCAL_DEF
void T2_Done_Face( T2_Face face )
{
#if 0
FT_Memory memory = face->root.memory;
FT_Stream stream = face->root.stream;
#endif
SFNT_Interface* sfnt = face->sfnt;
if (sfnt)
sfnt->done_face(face);
/* XXXXX: TO DO */
}
/*************************************************************************/
/* */
/* SIZE FUNCTIONS */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* T2_Init_Size */
/* */
/* <Description> */
/* Initializes a new OpenType size object. */
/* */
/* <InOut> */
/* size :: A handle to the size object. */
/* */
/* <Return> */
/* TrueType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error T2_Init_Size( T2_Size size )
{
UNUSED(size);
return 0;
}
/*************************************************************************/
/* */
/* <Function> */
/* T2_Done_Size */
/* */
/* <Description> */
/* The OpenType size object finalizer. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
LOCAL_FUNC
void T2_Done_Size( T2_Size size )
{
UNUSED(size);
}
/*************************************************************************/
/* */
/* <Function> */
/* T2_Reset_Size */
/* */
/* <Description> */
/* Resets a OpenType size when resolutions and character dimensions */
/* have been changed. */
/* */
/* <Input> */
/* size :: A handle to the target size object. */
/* */
LOCAL_DEF
FT_Error T2_Reset_Size( T2_Size size )
{
T2_Face face = (T2_Face)size->face;
FT_Size_Metrics* metrics = &size->metrics;
FT_Error error = FT_Err_Ok;
if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
return FT_Err_Invalid_Argument;
/* Compute root ascender, descender, test height, and max_advance */
metrics->ascender = ( FT_MulFix( face->root.ascender,
metrics->y_scale ) + 32 ) & -64;
metrics->descender = ( FT_MulFix( face->root.descender,
metrics->y_scale ) + 32 ) & -64;
metrics->height = ( FT_MulFix( face->root.height,
metrics->y_scale ) + 32 ) & -64;
metrics->max_advance = ( FT_MulFix( face->root.max_advance_width,
metrics->x_scale ) + 32 ) & -64;
return error;
}
/*************************************************************************/
/* */
/* <Function> */
/* T2_Init_GlyphSlot */
/* */
/* <Description> */
/* The OpenType glyph slot initializer. */
/* */
/* <Input> */
/* slot :: The glyph record to build. */
/* */
/* <Output> */
/* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error T2_Init_GlyphSlot( T2_GlyphSlot slot )
{
/* allocate the outline space */
FT_Face face = slot->face;
FT_Library library = face->driver->library;
FT_TRACE4(( "TT.Init_GlyphSlot: Creating outline maxp = %d, maxc = %d\n",
face->max_points, face->max_contours ));
return FT_Outline_New( library,
face->max_points + 2,
face->max_contours,
&slot->outline );
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Done_GlyphSlot */
/* */
/* <Description> */
/* The OpenType glyph slot finalizer. */
/* */
/* <Input> */
/* slot :: A handle to the glyph slot object. */
/* */
LOCAL_FUNC
void T2_Done_GlyphSlot( T2_GlyphSlot slot )
{
FT_Library library = slot->face->driver->library;
FT_Memory memory = library->memory;
if (slot->flags & ft_glyph_own_bitmap)
FREE( slot->bitmap.buffer );
FT_Outline_Done( library, &slot->outline );
return;
}
/*************************************************************************/
/* */
/* <Function> */
/* T2_Init_Driver */
/* */
/* <Description> */
/* Initializes a given OpenType driver object. */
/* */
/* <Input> */
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
/* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error T2_Init_Driver( T2_Driver driver )
{
FT_Memory memory = driver->root.memory;
FT_Error error;
error = FT_New_GlyphZone( memory, 0, 0, &driver->zone );
if (error) return error;
/* init extension registry if needed */
#ifdef T2_CONFIG_OPTION_EXTEND_ENGINE
return TT_Init_Extensions( driver );
#else
return FT_Err_Ok;
#endif
}
/*************************************************************************/
/* */
/* <Function> */
/* TT_Done_Driver */
/* */
/* <Description> */
/* Finalizes a given TrueType driver. */
/* */
/* <Input> */
/* driver :: A handle to the target TrueType driver. */
/* */
LOCAL_FUNC
void T2_Done_Driver( T2_Driver driver )
{
/* destroy extensions registry if needed */
#ifdef T2_CONFIG_OPTION_EXTEND_ENGINE
TT_Done_Extensions( driver );
#endif
/* remove the loading glyph zone */
FT_Done_GlyphZone( &driver->zone );
}
/* END */

141
src/cff/t2objs.h Normal file
View File

@ -0,0 +1,141 @@
/***************************************************************************/
/* */
/* t2objs.h */
/* */
/* Objects manager (specification). */
/* */
/* 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 T2OBJS_H
#define T2OBJS_H
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/t2types.h>
#include <t2errors.h>
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************/
/* */
/* <Type> */
/* T2_Driver */
/* */
/* <Description> */
/* A handle to an OpenType driver object. */
/* */
typedef struct T2_DriverRec_* T2_Driver;
typedef TT_Face T2_Face;
/*************************************************************************/
/* */
/* <Type> */
/* T2_Size */
/* */
/* <Description> */
/* A handle to an OpenType size object. */
/* */
typedef FT_Size T2_Size;
/*************************************************************************/
/* */
/* <Type> */
/* T2_GlyphSlot */
/* */
/* <Description> */
/* A handle to an OpenType glyph slot object. */
/* */
/* <Note> */
/* This is a direct typedef of FT_GlyphSlot, as there is nothing */
/* specific about the OpenType glyph slot. */
/* */
typedef FT_GlyphSlot T2_GlyphSlot;
/*************************************************************************/
/* */
/* Subglyph transformation record. */
/* */
typedef struct T2_Transform_
{
FT_Fixed xx, xy; /* transformation matrix coefficients */
FT_Fixed yx, yy;
FT_F26Dot6 ox, oy; /* offsets */
} T2_Transform;
/***********************************************************************/
/* */
/* TrueType driver class. */
/* */
typedef struct T2_DriverRec_
{
FT_DriverRec root;
FT_GlyphZone zone; /* glyph loader points zone */
void* extension_component;
} T2_DriverRec;
/*************************************************************************/
/* Face Funcs */
LOCAL_DEF FT_Error T2_Init_Face( FT_Stream stream,
T2_Face face,
TT_Int face_index,
TT_Int num_params,
FT_Parameter* params );
LOCAL_DEF void T2_Done_Face( T2_Face face );
/*************************************************************************/
/* Size funcs */
LOCAL_DEF FT_Error T2_Init_Size ( T2_Size size );
LOCAL_DEF void T2_Done_Size ( T2_Size size );
LOCAL_DEF FT_Error T2_Reset_Size( T2_Size size );
/*************************************************************************/
/* GlyphSlot funcs */
LOCAL_DEF FT_Error T2_Init_GlyphSlot( T2_GlyphSlot slot );
LOCAL_DEF void T2_Done_GlyphSlot( T2_GlyphSlot slot );
/*************************************************************************/
/* Driver funcs */
LOCAL_DEF FT_Error T2_Init_Driver( T2_Driver driver );
LOCAL_DEF void T2_Done_Driver( T2_Driver driver );
#ifdef __cplusplus
}
#endif
#endif /* T2OBJS_H */
/* END */

514
src/cff/t2parse.c Normal file
View File

@ -0,0 +1,514 @@
#include <t2parse.h>
#include <freetype/fterrors.h>
#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument
#define T2_Err_Syntax_Error FT_Err_Invalid_Argument
enum
{
t2_kind_none = 0,
t2_kind_num,
t2_kind_fixed,
t2_kind_string,
t2_kind_bool,
t2_kind_delta,
t2_kind_callback,
t2_kind_max /* do not remove */
};
/* now generate handlers for the most simple fields */
typedef FT_Error (*T2_Field_Reader)( T2_Parser* parser );
typedef struct T2_Field_Handler_
{
int kind;
int code;
FT_UInt offset;
FT_Byte size;
T2_Field_Reader reader;
FT_UInt array_max;
FT_UInt count_offset;
} T2_Field_Handler;
LOCAL_FUNC
void T2_Parser_Init( T2_Parser* parser, FT_UInt code, void* object )
{
MEM_Set(parser,0,sizeof(*parser));
parser->top = parser->stack;
parser->object_code = code;
parser->object = object;
}
/* reads an integer */
static
FT_Long parse_t2_integer( FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p = start;
FT_Int v = *p++;
FT_Long val = 0;
if (v == 28)
{
if ( p+2 > limit ) goto Bad;
val = ((FT_Long)p[0] << 8) | p[1];
p += 2;
}
else if (v == 29)
{
if ( p+4 > limit ) goto Bad;
val = ((FT_Long)p[0] << 24) |
((FT_Long)p[1] << 16) |
((FT_Long)p[2] << 8) | p[3];
p += 4;
}
else if (v < 247)
{
val = v - 139;
}
else if (v < 251)
{
if (p+1 > limit) goto Bad;
val = (v-247)*256 + p[0]+108;
p ++;
}
else
{
if (p+1 > limit) goto Bad;
val = -(v-251)*256 - p[0]-108;
p ++;
}
Exit:
return val;
Bad:
val = 0;
goto Exit;
}
/* reads a real */
static
FT_Fixed parse_t2_real( FT_Byte* start,
FT_Byte* limit,
FT_Int power_ten )
{
FT_Byte* p = start;
FT_Long num, divider, result, exp;
FT_Int sign = 0, exp_sign = 0;
FT_Byte nib;
FT_Byte phase;
result = 0;
num = 0;
divider = 1;
/* first of all, read the integer part */
phase = 4;
p--;
for (;;)
{
/* read one nibble at a time */
if (phase && ++p >= limit) goto Bad;
nib = (p[0] >> phase) & 0xF;
phase = 4-phase;
if (nib == 0xE)
sign = 1;
else if (nib > 9)
break;
else
result = result*10 + nib;
}
/* read decimal part, if any */
if (nib == 0xa)
for (;;)
{
/* read one nibble at a time */
if (!phase && ++p >= limit) goto Bad;
phase = 4-phase;
nib = (p[0] >> phase) & 0xF;
if (nib >= 10)
break;
if (divider < 10000000L)
{
num = num*10 + nib;
divider *= 10;
}
}
/* read exponent, if any */
if (nib == 12)
{
exp_sign = 1;
nib = 11;
}
if (nib == 11)
{
exp = 0;
for (;;)
{
/* read one nibble at a time */
if (!phase && ++p >= limit) goto Bad;
phase = 4-phase;
nib = (p[0] >> phase) & 0xF;
if (nib >= 10)
break;
exp = exp*10 + nib;
}
if (exp_sign)
exp = -exp;
power_ten += exp;
}
/* 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;
Exit:
return result;
Bad:
result = 0;
goto Exit;
}
/* reads a number, either integer or real */
static
FT_Long t2_parse_num( FT_Byte** d )
{
return ( **d == 30 ? (parse_t2_real ( d[0], d[1], 0 ) >> 16):
parse_t2_integer( d[0], d[1] ) );
}
/* reads a floating point number, either integer or real */
static
FT_Fixed t2_parse_fixed( FT_Byte** d )
{
return ( **d == 30 ? parse_t2_real( d[0], d[1], 0 ) :
parse_t2_integer( d[0], d[1] ) << 16 );
}
static
FT_Error parse_font_matrix( T2_Parser* parser )
{
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object;
FT_Matrix* matrix = &dict->font_matrix;
FT_Byte** data = parser->stack;
FT_Error error;
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 4)
{
matrix->xx = t2_parse_fixed( data++ );
matrix->yx = t2_parse_fixed( data++ );
matrix->xy = t2_parse_fixed( data++ );
matrix->yy = t2_parse_fixed( data );
error = 0;
}
return error;
}
static
FT_Error parse_font_bbox( T2_Parser* parser )
{
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object;
FT_BBox* bbox = &dict->font_bbox;
FT_Byte** data = parser->stack;
FT_Error error;
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 4)
{
bbox->xMin = t2_parse_fixed( data++ );
bbox->yMin = t2_parse_fixed( data++ );
bbox->xMax = t2_parse_fixed( data++ );
bbox->yMax = t2_parse_fixed( data );
error = 0;
}
return error;
}
static
FT_Error parse_private_dict( T2_Parser* parser )
{
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 2)
{
dict->private_offset = t2_parse_num( data++ );
dict->private_size = t2_parse_num( data );
error = 0;
}
return error;
}
static
FT_Error parse_cid_ros( T2_Parser* parser )
{
CFF_Top_Dict* dict = (CFF_Top_Dict*)parser->object;
FT_Byte** data = parser->stack;
FT_Error error;
error = T2_Err_Stack_Underflow;
if (parser->top >= parser->stack + 3)
{
dict->cid_registry = (FT_UInt)t2_parse_num( data++ );
dict->cid_ordering = (FT_UInt)t2_parse_num( data++ );
dict->cid_supplement = (FT_ULong)t2_parse_num( data );
error = 0;
}
return error;
}
#define T2_FIELD_NUM(code,name) T2_FIELD( code, name, t2_kind_num )
#define T2_FIELD_FIXED(code,name) T2_FIELD( code, name, t2_kind_fixed )
#define T2_FIELD_STRING(code,name) T2_FIELD( code, name, t2_kind_string )
#define T2_FIELD_BOOL(code,name) T2_FIELD( code, name, t2_kind_bool )
#define T2_FIELD_DELTA(code,name,max) T2_FIELD( code, name, t2_kind_delta )
#define T2_REF(s,f) (((s*)0)->f)
#define T2_FIELD_CALLBACK( code, name ) \
{ t2_kind_callback, code, 0, 0, parse_ ## name, 0, 0 },
#undef T2_FIELD
#define T2_FIELD( code, name, kind ) \
{ kind, code | T2CODE, \
(FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
sizeof( T2_REF( T2TYPE, name ) ), \
0 },
#undef T2_FIELD_DELTA
#define T2_FIELD_DELTA( code, name, max ) \
{ t2_kind_delta, code | T2CODE, \
(FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
sizeof( T2_REF( T2TYPE, name ) ), \
0, \
max, (FT_UInt)(char*)&T2_REF( T2TYPE, num_ ## name ) },
#define T2CODE_TOPDICT 0x1000
#define T2CODE_PRIVATE 0x2000
static const T2_Field_Handler t2_field_handlers[] =
{
#include <t2tokens.h>
{ 0, 0, 0, 0, 0, 0, 0 }
};
LOCAL_FUNC
FT_Error T2_Parser_Run( T2_Parser* parser,
FT_Byte* start,
FT_Byte* limit )
{
FT_Byte* p;
FT_Error error = 0;
parser->top = parser->stack;
parser->start = start;
parser->limit = limit;
parser->cursor = start;
while (p < limit)
{
FT_Byte v = *p;
if ( v >= 27 || v != 31 )
{
/* its a number, we'll push its position on the stack */
if (parser->top - parser->stack >= T2_MAX_STACK_DEPTH)
goto Stack_Overflow;
*parser->top ++ = p;
/* now, skip it */
if (v == 30)
{
/* skip real number */
for (;;)
{
if (p >= limit) goto Syntax_Error;
v = p[0] >> 4;
if (v == 15) break;
v = p[0] & 0xF;
if (v == 15) break;
p++;
}
p++;
}
else if (v == 28)
p += 2;
else if (v == 29)
p += 4;
else if (v > 246)
p += 1;
}
else
{
/* this is not a number, hence it's an operator. Compute its code */
/* and look for it in our current list.. */
FT_UInt code;
FT_Int num_args = parser->top - parser->stack;
const T2_Field_Handler* field;
/* first of all, a trivial check */
if ( num_args < 1 ) goto Stack_Underflow;
code = v;
if (v == 12)
{
/* two byte operator */
p++;
code = 0x100 | p[0];
}
code = code | parser->object_code;
for ( field = t2_field_handlers; field->kind; field++ )
{
if (field->code == code)
{
/* we found our field's handler, read it.. */
FT_Long val;
FT_Byte* q = (FT_Byte*)parser->object + field->offset;
switch (field->kind)
{
case t2_kind_bool:
case t2_kind_string:
case t2_kind_num:
val = t2_parse_num( parser->stack );
goto Store_Number;
case t2_kind_fixed:
val = t2_parse_fixed( parser->stack );
Store_Number:
switch (field->size)
{
case 1: *(FT_Byte*) q = (FT_Byte)val; break;
case 2: *(FT_Short*)q = (FT_Short)val; break;
default: *(FT_Long*)q = val;
}
break;
case t2_kind_delta:
{
FT_Byte* qcount = (FT_Byte*)parser->object +
field->count_offset;
FT_Long val;
FT_Byte** data = parser->stack;
if (num_args > field->array_max)
num_args = field->array_max;
/* store count */
*qcount = (FT_Byte)num_args;
val = 0;
while (num_args > 0)
{
val += t2_parse_num( data++ );
switch (field->size)
{
case 1: *(FT_Byte*) q = (FT_Byte)val; break;
case 2: *(FT_Short*)q = (FT_Short)val; break;
default: *(FT_Long*)q = val;
}
q += field->size;
num_args--;
}
}
break;
default: /* callback */
error = field->reader( parser );
if (error) goto Exit;
}
/* clear stack */
parser->top = parser->stack;
}
goto Found; /* exit loop */
}
/* this is an unknown operator, or it is unsupported, we will ignore */
/* it for now... */
Found:
/* clear stack */
parser->top = parser->stack;
}
p++;
}
Exit:
return error;
Stack_Overflow:
error = FT_Err_Invalid_Argument;
goto Exit;
Stack_Underflow:
error = FT_Err_Invalid_Argument;
goto Exit;
Syntax_Error:
error = FT_Err_Invalid_Argument;
goto Exit;
}

33
src/cff/t2parse.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef T2PARSE_H
#define T2PARSE_H
#include <freetype/internal/t2types.h>
#include <freetype/internal/ftobjs.h>
#define T2_MAX_STACK_DEPTH 96
typedef struct T2_Parser_
{
FT_Byte* start;
FT_Byte* limit;
FT_Byte* cursor;
FT_Byte* stack[ T2_MAX_STACK_DEPTH+1 ];
FT_Byte** top;
FT_UInt object_code;
void* object;
} T2_Parser;
LOCAL_DEF
void T2_Parser_Init( T2_Parser* parser, FT_UInt code, void* object );
LOCAL_DEF
FT_Error T2_Parser_Run( T2_Parser* parser,
FT_Byte* start,
FT_Byte* limit );
#endif /* T2PARSE_H */

76
src/cff/t2tokens.h Normal file
View File

@ -0,0 +1,76 @@
#undef T2TYPE
#undef T2CODE
#define T2TYPE CFF_Top_Dict
#define T2CODE T2CODE_TOPDICT
T2_FIELD_STRING ( 0, version )
T2_FIELD_STRING ( 1, notice )
T2_FIELD_STRING ( 0x100, copyright )
T2_FIELD_STRING ( 2, full_name )
T2_FIELD_STRING ( 3, family_name )
T2_FIELD_STRING ( 4, weight )
T2_FIELD_BOOL ( 0x101, is_fixed_pitch )
T2_FIELD_FIXED ( 0x102, italic_angle )
T2_FIELD_NUM ( 0x103, underline_position )
T2_FIELD_NUM ( 0x104, underline_thickness )
T2_FIELD_NUM ( 0x105, paint_type )
T2_FIELD_NUM ( 0x106, charstring_type )
T2_FIELD_CALLBACK( 0x107, font_matrix )
T2_FIELD_NUM ( 13, unique_id )
T2_FIELD_CALLBACK( 5, font_bbox )
T2_FIELD_NUM ( 0x108, stroke_width )
T2_FIELD_NUM ( 15, charset_offset )
T2_FIELD_NUM ( 16, encoding_offset )
T2_FIELD_NUM ( 17, charstrings_offset )
T2_FIELD_CALLBACK( 18, private_dict )
T2_FIELD_NUM ( 0x114, synthetic_base )
T2_FIELD_STRING ( 0x115, postscript )
T2_FIELD_STRING ( 0x116, base_font_name )
#if 0
T2_FIELD_DELTA ( 0x117, base_font_blend, 16 )
T2_FIELD_CALLBACK( 0x118, multiple_master )
T2_FIELD_CALLBACK( 0x119, blend_axit_types )
#endif
T2_FIELD_CALLBACK( 0x11E, cid_ros )
T2_FIELD_NUM ( 0x11F, cid_font_version )
T2_FIELD_NUM ( 0x120, cid_font_revision )
T2_FIELD_NUM ( 0x121, cid_font_type )
T2_FIELD_NUM ( 0x122, cid_count )
T2_FIELD_NUM ( 0x123, cid_uid_base )
T2_FIELD_NUM ( 0x124, cid_fd_array_offset )
T2_FIELD_NUM ( 0x125, cid_fd_select_offset )
T2_FIELD_STRING ( 0x126, cid_font_name )
#if 0
T2_FIELD_NUM ( 0x127, chameleon )
#endif
#undef T2TYPE
#undef T2CODE
#define T2TYPE CFF_Private
#define T2CODE T2CODE_PRIVATE
T2_FIELD_DELTA( 6, blue_values, 14 )
T2_FIELD_DELTA( 7, other_blues, 10 )
T2_FIELD_DELTA( 8, family_blues, 14 )
T2_FIELD_DELTA( 9, family_other_blues, 10 )
T2_FIELD_FIXED( 0x109, blue_scale )
T2_FIELD_NUM ( 0x10A, blue_shift )
T2_FIELD_NUM ( 0x10B, blue_fuzz )
T2_FIELD_NUM ( 10, standard_width )
T2_FIELD_NUM ( 11, standard_height )
T2_FIELD_DELTA( 0x10C, snap_widths, 13 )
T2_FIELD_DELTA( 0x10D, snap_heights, 13 )
T2_FIELD_BOOL ( 0x10E, force_bold )
T2_FIELD_FIXED( 0x10F, force_bold_threshold )
T2_FIELD_NUM ( 0x110, lenIV )
T2_FIELD_NUM ( 0x111, language_group )
T2_FIELD_FIXED( 0x112, expansion_factor )
T2_FIELD_NUM ( 0x113, initial_random_seed )
T2_FIELD_NUM ( 19, local_subrs_offset )
T2_FIELD_NUM ( 20, default_width )
T2_FIELD_NUM ( 21, nominal_width )