ref: 4f99c3c4234bcc233eb4057cc33dd5e21f3eda27
parent: a519b3b7a34a75fae18e4fb2acd054bbeb80104a
author: David Turner <[email protected]>
date: Mon May 29 16:55:13 EDT 2000
fixed divide by zero bug added CFF/OpenType driver source (not working for now)
--- a/CHANGES
+++ b/CHANGES
@@ -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..)
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -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,15 +344,14 @@
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);
@@ -359,6 +358,8 @@
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;
}
--- /dev/null
+++ b/src/cff/cff.c
@@ -1,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 */
--- /dev/null
+++ b/src/cff/module.mk
@@ -1,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
--- /dev/null
+++ b/src/cff/rules.mk
@@ -1,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
--- /dev/null
+++ b/src/cff/t2driver.c
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2driver.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2errors.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2gload.c
@@ -1,0 +1,1177 @@
+/***************************************************************************/
+/* */
+/* t2gload.c */
+/* */
+/* OpenType Glyph 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/ftcalc.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/sfnt.h>
+#include <freetype/tttags.h>
+
+
+#include <t2gload.h>
+
+ /* required for the tracing mode */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_ttgload
+
+
+ /*************************************************************************/
+ /* */
+ /* Composite font flags. */
+ /* */
+#define ARGS_ARE_WORDS 0x001
+#define ARGS_ARE_XY_VALUES 0x002
+#define ROUND_XY_TO_GRID 0x004
+#define WE_HAVE_A_SCALE 0x008
+/* reserved 0x010 */
+#define MORE_COMPONENTS 0x020
+#define WE_HAVE_AN_XY_SCALE 0x040
+#define WE_HAVE_A_2X2 0x080
+#define WE_HAVE_INSTR 0x100
+#define USE_MY_METRICS 0x200
+
+
+
+ /*************************************************************************/
+ /* 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). */
+ /* */
+ LOCAL_FUNC
+ void T2_Get_Metrics( TT_HoriHeader* header,
+ FT_UInt index,
+ FT_Short* bearing,
+ FT_UShort* advance )
+ {
+ TT_LongMetrics* longs_m;
+ TT_UShort k = header->number_Of_HMetrics;
+
+
+ if ( index < k )
+ {
+ longs_m = (TT_LongMetrics*)header->long_metrics + index;
+ *bearing = longs_m->bearing;
+ *advance = longs_m->advance;
+ }
+ else
+ {
+ *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
+ *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* Returns the horizontal metrics in font units for a given glyph. */
+ /* If `check' is true, take care of monospaced fonts by returning the */
+ /* advance width maximum. */
+ /* */
+ static
+ void Get_HMetrics( T2_Face face,
+ FT_UInt index,
+ FT_Bool check,
+ FT_Short* lsb,
+ FT_UShort* aw )
+ {
+ T2_Get_Metrics( &face->horizontal, index, lsb, aw );
+
+ if ( check && face->postscript.isFixedPitch )
+ *aw = face->horizontal.advance_Width_Max;
+ }
+
+
+ /*************************************************************************/
+ /* Returns the advance width table for a given pixel size if it is */
+ /* found in the font's `hdmx' table (if any). */
+ /* */
+ static
+ FT_Byte* Get_Advance_Widths( T2_Face face,
+ FT_UShort ppem )
+ {
+ FT_UShort n;
+
+ for ( n = 0; n < face->hdmx.num_records; n++ )
+ if ( face->hdmx.records[n].ppem == ppem )
+ return face->hdmx.records[n].widths;
+
+ return NULL;
+ }
+
+
+#define cur_to_org( n, zone ) \
+ MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( TT_Vector ) )
+
+#define org_to_cur( n, zone ) \
+ MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( TT_Vector ) )
+
+
+ /*************************************************************************/
+ /* Translates an array of coordinates. */
+ /* */
+ static
+ void translate_array( FT_UInt n,
+ FT_Vector* coords,
+ FT_Pos delta_x,
+ FT_Pos delta_y )
+ {
+ FT_UInt k;
+
+ if ( delta_x )
+ for ( k = 0; k < n; k++ )
+ coords[k].x += delta_x;
+
+ if ( delta_y )
+ for ( k = 0; k < n; k++ )
+ coords[k].y += delta_y;
+ }
+
+
+
+ /*************************************************************************/
+ /* Mounts one glyph zone on top of another. This is needed to */
+ /* assemble composite glyphs. */
+ /* */
+ static
+ void mount_zone( FT_GlyphZone* source,
+ FT_GlyphZone* target )
+ {
+ FT_UInt np;
+ FT_Int nc;
+
+ np = source->n_points;
+ nc = source->n_contours;
+
+ target->org = source->org + np;
+ target->cur = source->cur + np;
+ target->tags = source->tags + np;
+
+ target->contours = source->contours + nc;
+
+ target->n_points = 0;
+ target->n_contours = 0;
+ }
+
+
+#undef IS_HINTED
+#define IS_HINTED(flags) ((flags & FT_LOAD_NO_HINTING) == 0)
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Load_Simple_Glyph */
+ /* */
+ /* <Description> */
+ /* Loads a simple (i.e, non-composite) glyph. This function is used */
+ /* for the `Load_Simple' state of TT_Load_Glyph(). All composite */
+ /* glyphs elements will be loaded with routine. */
+ /* */
+ static
+ FT_Error Load_Simple( T2_Loader* load,
+ FT_UInt byte_count,
+ FT_Int n_contours,
+ FT_Bool debug )
+ {
+ FT_Error error;
+ FT_Stream stream = load->stream;
+ FT_GlyphZone* zone = &load->zone;
+ T2_Face face = load->face;
+
+ FT_UShort n_ins;
+ FT_Int n, n_points;
+
+ /*********************************************************************/
+ /* simple check */
+
+ if ( n_contours > load->left_contours )
+ {
+ FT_TRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",
+ load->glyph_index,
+ n_contours,
+ load->left_contours ));
+ return TT_Err_Too_Many_Contours;
+ }
+
+ /* preparing the execution context */
+ mount_zone( &load->base, zone );
+
+ /*********************************************************************/
+ /* reading the contours endpoints */
+
+ if ( ACCESS_Frame( byte_count ) )
+ return error;
+
+ for ( n = 0; n < n_contours; n++ )
+ zone->contours[n] = GET_UShort();
+
+ n_points = 0;
+ if ( n_contours > 0 )
+ n_points = zone->contours[n_contours - 1] + 1;
+
+
+ /*********************************************************************/
+ /* reading the bytecode instructions */
+
+ n_ins = GET_UShort();
+ load->face->root.glyph->control_len = n_ins;
+
+ if ( n_points > load->left_points )
+ {
+ FT_TRACE0(( "ERROR: Too many points in glyph %ld\n", load->glyph_index ));
+ error = TT_Err_Too_Many_Points;
+ goto Fail;
+ }
+
+ FT_TRACE4(( "Instructions size : %d\n", n_ins ));
+
+ if ( n_ins > face->max_profile.maxSizeOfInstructions )
+ {
+ FT_TRACE0(( "ERROR: Too many instructions!\n" ));
+ error = TT_Err_Too_Many_Ins;
+ goto Fail;
+ }
+
+ if (stream->cursor + n_ins > stream->limit)
+ {
+ FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
+ error = TT_Err_Too_Many_Ins;
+ goto Fail;
+ }
+
+ stream->cursor += n_ins;
+
+ /*********************************************************************/
+ /* reading the point tags */
+
+ {
+ FT_Byte* flag = load->zone.tags;
+ FT_Byte* limit = flag + n_points;
+ FT_Byte c, count;
+
+ for (; flag < limit; flag++)
+ {
+ *flag = c = GET_Byte();
+ if ( c & 8 )
+ {
+ for ( count = GET_Byte(); count > 0; count-- )
+ *++flag = c;
+ }
+ }
+ }
+
+ /*********************************************************************/
+ /* reading the X coordinates */
+
+ {
+ FT_Vector* vec = zone->org;
+ FT_Vector* limit = vec + n_points;
+ FT_Byte* flag = zone->tags;
+ FT_Pos x = 0;
+
+ for ( ; vec < limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+
+ if ( *flag & 2 )
+ {
+ y = GET_Byte();
+ if ((*flag & 16) == 0) y = -y;
+ }
+ else if ((*flag & 16) == 0)
+ y = GET_Short();
+
+ x += y;
+ vec->x = x;
+ }
+ }
+
+ /*********************************************************************/
+ /* reading the Y coordinates */
+
+ {
+ FT_Vector* vec = zone->org;
+ FT_Vector* limit = vec + n_points;
+ FT_Byte* flag = zone->tags;
+ FT_Pos x = 0;
+
+ for ( ; vec < limit; vec++, flag++ )
+ {
+ FT_Pos y = 0;
+
+ if ( *flag & 4 )
+ {
+ y = GET_Byte();
+ if ((*flag & 32) == 0) y = -y;
+ }
+ else if ((*flag & 32) == 0)
+ y = GET_Short();
+
+ x += y;
+ vec->y = x;
+ }
+ }
+
+ FORGET_Frame();
+
+ /*********************************************************************/
+ /* Add shadow points */
+
+ /* Now add the two shadow points at n and n + 1. */
+ /* We need the left side bearing and advance width. */
+
+ {
+ FT_Vector* pp1;
+ FT_Vector* pp2;
+
+ /* pp1 = xMin - lsb */
+ pp1 = zone->org + n_points;
+ pp1->x = load->bbox.xMin - load->left_bearing;
+ pp1->y = 0;
+
+ /* pp2 = pp1 + aw */
+ pp2 = pp1 + 1;
+ pp2->x = pp1->x + load->advance;
+ pp2->y = 0;
+
+ /* clear the touch tags */
+ for ( n = 0; n < n_points; n++ )
+ zone->tags[n] &= FT_Curve_Tag_On;
+
+ zone->tags[n_points ] = 0;
+ zone->tags[n_points + 1] = 0;
+ }
+ /* Note that we return two more points that are not */
+ /* part of the glyph outline. */
+
+ zone->n_points = n_points;
+ zone->n_contours = n_contours;
+ n_points += 2;
+
+ /*******************************************/
+ /* now eventually scale and hint the glyph */
+
+ if (load->load_flags & FT_LOAD_NO_SCALE)
+ {
+ /* no scaling, just copy the orig arrays into the cur ones */
+ org_to_cur( n_points, zone );
+ }
+ else
+ {
+ FT_Vector* vec = zone->org;
+ FT_Vector* limit = vec + n_points;
+ FT_Fixed x_scale = load->size->root.metrics.x_scale;
+ FT_Fixed y_scale = load->size->root.metrics.y_scale;
+
+ /* first scale the glyph points */
+ for (; vec < limit; vec++)
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ /* if hinting, round pp1, and shift the glyph accordingly */
+ if ( !IS_HINTED(load->load_flags) )
+ {
+ org_to_cur( n_points, zone );
+ }
+ else
+ {
+ FT_Pos x = zone->org[n_points-2].x;
+ x = ((x + 32) & -64) - x;
+ translate_array( n_points, zone->org, x, 0 );
+
+ org_to_cur( n_points, zone );
+
+ zone->cur[n_points-1].x = (zone->cur[n_points-1].x + 32) & -64;
+
+ }
+ }
+
+ /* save glyph phantom points */
+ if ( !load->preserve_pps )
+ {
+ load->pp1 = zone->cur[n_points - 2];
+ load->pp2 = zone->cur[n_points - 1];
+ }
+
+ return FT_Err_Ok;
+
+ Fail:
+ FORGET_Frame();
+ return error;
+ }
+
+
+
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* load_opentype_glyph */
+ /* */
+ /* <Description> */
+ /* Loads a given truetype glyph. Handles composites and uses a */
+ /* T2_Loader object.. */
+ /* */
+ static
+ FT_Error load_opentype_glyph( T2_Loader* loader,
+ FT_UInt glyph_index )
+ {
+ FT_Stream stream = loader->stream;
+ FT_Error error;
+ T2_Face face = loader->face;
+ FT_ULong offset;
+ FT_Int num_subglyphs = 0, contours_count;
+ FT_UInt index, num_points, num_contours, count;
+ FT_Fixed x_scale, y_scale;
+ FT_ULong ins_offset;
+
+ /* check glyph index */
+ index = glyph_index;
+ if ( index >= (TT_UInt)face->root.num_glyphs )
+ {
+ error = TT_Err_Invalid_Glyph_Index;
+ goto Fail;
+ }
+
+ loader->glyph_index = glyph_index;
+ num_contours = 0;
+ num_points = 0;
+ ins_offset = 0;
+
+ x_scale = 0x10000;
+ y_scale = 0x10000;
+ if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
+ {
+ x_scale = loader->size->root.metrics.x_scale;
+ y_scale = loader->size->root.metrics.y_scale;
+ }
+
+ /* get horizontal metrics */
+ {
+ FT_Short left_bearing;
+ FT_UShort advance_width;
+
+ Get_HMetrics( face, index,
+ (FT_Bool)!(loader->load_flags &
+ FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
+ &left_bearing,
+ &advance_width );
+
+ loader->left_bearing = left_bearing;
+ loader->advance = advance_width;
+ }
+
+ /* load glyph header */
+ offset = face->glyph_locations[index];
+ count = 0;
+ if (index < (TT_UInt)face->num_locations-1)
+ count = face->glyph_locations[index+1] - offset;
+
+
+ if (count == 0)
+ {
+ /* as described by Frederic Loyer, these are spaces, and */
+ /* not the unknown glyph. */
+ loader->bbox.xMin = 0;
+ loader->bbox.xMax = 0;
+ loader->bbox.yMin = 0;
+ loader->bbox.yMax = 0;
+
+ loader->pp1.x = 0;
+ loader->pp2.x = loader->advance;
+
+ if ( (loader->load_flags & FT_LOAD_NO_SCALE)==0 )
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+
+ goto Load_End;
+ }
+
+ offset = loader->glyf_offset + offset;
+
+ /* read first glyph header */
+ if ( FILE_Seek( offset ) || ACCESS_Frame( 10L ) )
+ goto Fail;
+
+ contours_count = GET_Short();
+
+ loader->bbox.xMin = GET_Short();
+ loader->bbox.yMin = GET_Short();
+ loader->bbox.xMax = GET_Short();
+ loader->bbox.yMax = GET_Short();
+
+ FORGET_Frame();
+
+ FT_TRACE6(( "Glyph %ld\n", index ));
+ FT_TRACE6(( " # of contours : %d\n", num_contours ));
+ FT_TRACE6(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
+ loader->bbox.xMax ));
+ FT_TRACE6(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
+ loader->bbox.yMax ));
+ FT_TRACE6(( "-" ));
+
+ count -= 10;
+
+ if ( contours_count > loader->left_contours )
+ {
+ FT_TRACE0(( "ERROR: Too many contours for glyph %ld\n", index ));
+ error = TT_Err_Too_Many_Contours;
+ goto Fail;
+ }
+
+ loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+ loader->pp1.y = 0;
+ loader->pp2.x = loader->pp1.x + loader->advance;
+ loader->pp2.y = 0;
+
+ if ((loader->load_flags & FT_LOAD_NO_SCALE)==0)
+ {
+ loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
+ loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+ }
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /**********************************************************************/
+ /* if it is a simple glyph, load it */
+ if (contours_count >= 0)
+ {
+ FT_UInt num_base_points;
+
+ error = Load_Simple( loader, count, contours_count, 0 );
+ if ( error ) goto Fail;
+
+ /* Note: We could have put the simple loader source there */
+ /* but the code is fat enough already :-) */
+ num_points = loader->zone.n_points;
+ num_contours = loader->zone.n_contours;
+
+ num_base_points = loader->base.n_points;
+ {
+ FT_UInt k;
+ for ( k = 0; k < num_contours; k++ )
+ loader->zone.contours[k] += num_base_points;
+ }
+
+ loader->base.n_points += num_points;
+ loader->base.n_contours += num_contours;
+
+ loader->zone.n_points = 0;
+ loader->zone.n_contours = 0;
+
+ loader->left_points -= num_points;
+ loader->left_contours -= num_contours;
+ }
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /************************************************************************/
+ else /* otherwise, load a composite !! */
+ {
+ /* for each subglyph, read composite header */
+ T2_GlyphSlot glyph = loader->glyph;
+ FT_SubGlyph* subglyph = glyph->subglyphs + glyph->num_subglyphs;
+
+ if (ACCESS_Frame(count)) goto Fail;
+
+ num_subglyphs = 0;
+ do
+ {
+ TT_Fixed xx, xy, yy, yx;
+ FT_UInt total_subglyphs;
+
+ /* grow the 'glyph->subglyphs' table if necessary */
+ total_subglyphs = glyph->num_subglyphs + num_subglyphs;
+ if ( total_subglyphs >= glyph->max_subglyphs )
+ {
+ FT_UInt new_max = glyph->max_subglyphs;
+ FT_Memory memory = loader->face->root.memory;
+
+ while (new_max <= total_subglyphs)
+ new_max += 4;
+
+ if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+ new_max, FT_SubGlyph ) )
+ goto Fail;
+
+ glyph->max_subglyphs = new_max;
+ subglyph = glyph->subglyphs + glyph->num_subglyphs + num_subglyphs;
+ }
+
+ subglyph->arg1 = subglyph->arg2 = 0;
+
+ subglyph->flags = GET_UShort();
+ subglyph->index = GET_UShort();
+
+ /* read arguments */
+ if (subglyph->flags & ARGS_ARE_WORDS)
+ {
+ subglyph->arg1 = GET_Short();
+ subglyph->arg2 = GET_Short();
+ }
+ else
+ {
+ subglyph->arg1 = GET_Char();
+ subglyph->arg2 = GET_Char();
+ }
+
+ /* read transform */
+ xx = yy = 0x10000;
+ xy = yx = 0;
+
+ if (subglyph->flags & WE_HAVE_A_SCALE)
+ {
+ xx = (TT_Fixed)GET_Short() << 2;
+ yy = xx;
+ }
+ else if (subglyph->flags & WE_HAVE_AN_XY_SCALE)
+ {
+ xx = (TT_Fixed)GET_Short() << 2;
+ yy = (TT_Fixed)GET_Short() << 2;
+ }
+ else if (subglyph->flags & WE_HAVE_A_2X2)
+ {
+ xx = (TT_Fixed)GET_Short() << 2;
+ xy = (TT_Fixed)GET_Short() << 2;
+ yx = (TT_Fixed)GET_Short() << 2;
+ yy = (TT_Fixed)GET_Short() << 2;
+ }
+
+ subglyph->transform.xx = xx;
+ subglyph->transform.xy = xy;
+ subglyph->transform.yx = yx;
+ subglyph->transform.yy = yy;
+
+ subglyph++;
+ num_subglyphs++;
+ }
+ while (subglyph[-1].flags & MORE_COMPONENTS);
+
+ FORGET_Frame();
+
+ /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+ /* "as is" in the glyph slot (the client application will be */
+ /* responsible for interpreting this data..) */
+ if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+ {
+ /* set up remaining glyph fields */
+ glyph->num_subglyphs += num_subglyphs;
+ glyph->format = ft_glyph_format_composite;
+ goto Load_End;
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*********************************************************************/
+ /* Now, read each subglyph independently.. */
+ {
+ FT_Int n, num_base_points, num_new_points;
+
+ subglyph = glyph->subglyphs + glyph->num_subglyphs;
+ glyph->num_subglyphs += num_subglyphs;
+
+ for ( n = 0; n < num_subglyphs; n++, subglyph++ )
+ {
+ FT_Vector pp1, pp2;
+ FT_Pos x, y;
+
+ pp1 = loader->pp1;
+ pp2 = loader->pp2;
+
+ num_base_points = loader->base.n_points;
+
+ error = load_truetype_glyph( loader, subglyph->index );
+ if (error) goto Fail;
+
+ if ( subglyph->flags & USE_MY_METRICS )
+ {
+ pp1 = loader->pp1;
+ pp2 = loader->pp2;
+ }
+ else
+ {
+ loader->pp1 = pp1;
+ loader->pp2 = pp2;
+ }
+
+ num_points = loader->base.n_points;
+ num_contours = loader->base.n_contours;
+
+ num_new_points = num_points - num_base_points;
+
+ /********************************************************/
+ /* now perform the transform required for this subglyph */
+
+ if ( subglyph->flags & ( WE_HAVE_A_SCALE |
+ WE_HAVE_AN_XY_SCALE |
+ WE_HAVE_A_2X2 ) )
+ {
+ FT_Vector* cur = loader->zone.cur;
+ FT_Vector* org = loader->zone.org;
+ FT_Vector* limit = cur + num_new_points;
+
+ for ( ; cur < limit; cur++, org++ )
+ {
+ TT_Pos nx, ny;
+
+ nx = FT_MulFix( cur->x, subglyph->transform.xx ) +
+ FT_MulFix( cur->y, subglyph->transform.yx );
+
+ ny = FT_MulFix( cur->x, subglyph->transform.xy ) +
+ FT_MulFix( cur->y, subglyph->transform.yy );
+
+ cur->x = nx;
+ cur->y = ny;
+
+ nx = FT_MulFix( org->x, subglyph->transform.xx ) +
+ FT_MulFix( org->y, subglyph->transform.yx );
+
+ ny = FT_MulFix( org->x, subglyph->transform.xy ) +
+ FT_MulFix( org->y, subglyph->transform.yy );
+
+ org->x = nx;
+ org->y = ny;
+ }
+ }
+
+ /* apply offset */
+
+ if ( !(subglyph->flags & ARGS_ARE_XY_VALUES) )
+ {
+ FT_Int k = subglyph->arg1;
+ FT_UInt l = subglyph->arg2;
+
+ if ( k >= num_base_points ||
+ l >= (TT_UInt)num_new_points )
+ {
+ error = TT_Err_Invalid_Composite;
+ goto Fail;
+ }
+
+ l += num_base_points;
+
+ x = loader->base.cur[k].x - loader->base.cur[l].x;
+ y = loader->base.cur[k].y - loader->base.cur[l].y;
+ }
+ else
+ {
+ x = subglyph->arg1;
+ y = subglyph->arg2;
+
+ if (!(loader->load_flags & FT_LOAD_NO_SCALE))
+ {
+ x = FT_MulFix( x, x_scale );
+ y = FT_MulFix( y, y_scale );
+
+ if ( subglyph->flags & ROUND_XY_TO_GRID )
+ {
+ x = (x + 32) & -64;
+ y = (y + 32) & -64;
+ }
+ }
+ }
+
+ translate_array( num_new_points, loader->zone.cur, x, y );
+ cur_to_org( num_new_points, &loader->zone );
+ }
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* we have finished loading all sub-glyphs, now, look for */
+ /* instructions for this composite !! */
+
+ }
+ /* end of composite loading */
+ }
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ Load_End:
+ error = FT_Err_Ok;
+
+ Fail:
+ return error;
+ }
+
+
+
+
+
+ static
+ void compute_glyph_metrics( T2_Loader* loader,
+ FT_UInt glyph_index )
+ {
+ FT_UInt num_points = loader->base.n_points;
+ FT_UInt num_contours = loader->base.n_contours;
+ FT_BBox bbox;
+ T2_Face face = loader->face;
+ FT_Fixed x_scale, y_scale;
+ T2_GlyphSlot glyph = loader->glyph;
+ T2_Size size = loader->size;
+
+ /* when a simple glyph was loaded, the value of */
+ /* "base.n_points" and "base.n_contours" is 0, we must */
+ /* take those in the "zone" instead.. */
+ if ( num_points == 0 && num_contours == 0 )
+ {
+ num_points = loader->zone.n_points;
+ num_contours = loader->zone.n_contours;
+ }
+
+ x_scale = 0x10000;
+ y_scale = 0x10000;
+ if ( (loader->load_flags & FT_LOAD_NO_SCALE) == 0)
+ {
+ x_scale = size->root.metrics.x_scale;
+ y_scale = size->root.metrics.y_scale;
+ }
+
+ if ( glyph->format != ft_glyph_format_composite )
+ {
+ FT_UInt u;
+ for ( u = 0; u < num_points + 2; u++ )
+ {
+ glyph->outline.points[u] = loader->base.cur[u];
+ glyph->outline.tags [u] = loader->base.tags[u];
+ }
+
+ for ( u = 0; u < num_contours; u++ )
+ glyph->outline.contours[u] = loader->base.contours[u];
+
+ /* glyph->outline.second_pass = TRUE; */
+ glyph->outline.flags &= ~ft_outline_single_pass;
+ glyph->outline.n_points = num_points;
+ glyph->outline.n_contours = num_contours;
+
+ /* translate array so that (0,0) is the glyph's origin */
+ translate_array( (TT_UShort)(num_points + 2),
+ glyph->outline.points,
+ -loader->pp1.x,
+ 0 );
+
+ FT_Outline_Get_CBox( &glyph->outline, &bbox );
+
+ if ( IS_HINTED(loader->load_flags) )
+ {
+ /* grid-fit the bounding box */
+ bbox.xMin &= -64;
+ bbox.yMin &= -64;
+ bbox.xMax = (bbox.xMax + 63) & -64;
+ bbox.yMax = (bbox.yMax + 63) & -64;
+ }
+ }
+ else
+ bbox = loader->bbox;
+
+ /* get the device-independent scaled horizontal metrics */
+ /* take care of fixed-pitch fonts... */
+ {
+ FT_Pos left_bearing;
+ FT_Pos advance;
+
+ left_bearing = loader->left_bearing;
+ advance = loader->advance;
+
+ /* the flag FT_LOAD_NO_ADVANCE_CHECK was introduced to */
+ /* correctly support DynaLab fonts, who have an incorrect */
+ /* "advance_Width_Max" field !! It is used, to my knowledge */
+ /* exclusively in the X-TrueType font server.. */
+ /* */
+ if ( face->postscript.isFixedPitch &&
+ (loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) == 0 )
+ advance = face->horizontal.advance_Width_Max;
+
+ if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+ {
+ left_bearing = FT_MulFix( left_bearing, x_scale );
+ advance = FT_MulFix( advance, x_scale );
+ }
+
+ glyph->metrics2.horiBearingX = left_bearing;
+ glyph->metrics2.horiAdvance = advance;
+ }
+
+ glyph->metrics.horiBearingX = bbox.xMin;
+ glyph->metrics.horiBearingY = bbox.yMax;
+ glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+
+ /* Now take care of vertical metrics. In the case where there is */
+ /* no vertical information within the font (relatively common), make */
+ /* up some metrics by `hand'... */
+
+ {
+ FT_Short top_bearing; /* vertical top side bearing (EM units) */
+ FT_UShort advance_height; /* vertical advance height (EM units) */
+
+ FT_Pos left; /* scaled vertical left side bearing */
+ FT_Pos Top; /* scaled original vertical top side bearing */
+ FT_Pos top; /* scaled vertical top side bearing */
+ FT_Pos advance; /* scaled vertical advance height */
+
+
+ /* Get the unscaled `tsb' and `ah' */
+ if ( face->vertical_info &&
+ face->vertical.number_Of_VMetrics > 0 )
+ {
+ /* Don't assume that both the vertical header and vertical */
+ /* metrics are present in the same font :-) */
+
+ T2_Get_Metrics( (TT_HoriHeader*)&face->vertical,
+ glyph_index,
+ &top_bearing,
+ &advance_height );
+ }
+ else
+ {
+ /* Make up the distances from the horizontal header.. */
+
+ /* NOTE: The OS/2 values are the only `portable' ones, */
+ /* which is why we use them, when there is an */
+ /* OS/2 table in the font. Otherwise, we use the */
+ /* values defined in the horizontal header.. */
+ /* */
+ /* NOTE2: The sTypoDescender is negative, which is why */
+ /* we compute the baseline-to-baseline distance */
+ /* here with: */
+ /* ascender - descender + linegap */
+ /* */
+ if ( face->os2.version != 0xFFFF )
+ {
+ top_bearing = face->os2.sTypoLineGap / 2;
+ advance_height = (TT_UShort)(face->os2.sTypoAscender -
+ face->os2.sTypoDescender +
+ face->os2.sTypoLineGap);
+ }
+ else
+ {
+ top_bearing = face->horizontal.Line_Gap / 2;
+ advance_height = (TT_UShort)(face->horizontal.Ascender +
+ face->horizontal.Descender +
+ face->horizontal.Line_Gap);
+ }
+ }
+
+ /* We must adjust the top_bearing value from the bounding box given
+ in the glyph header to te bounding box calculated with
+ TT_Get_Outline_BBox() */
+
+ /* scale the metrics */
+ if ( !(loader->load_flags & FT_LOAD_NO_SCALE) )
+ {
+ Top = FT_MulFix( top_bearing, y_scale );
+ top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
+ - bbox.yMax;
+ advance = FT_MulFix( advance_height, y_scale );
+ }
+ else
+ {
+ Top = top_bearing;
+ top = top_bearing + loader->bbox.yMax - bbox.yMax;
+ advance = advance_height;
+ }
+
+ glyph->metrics2.vertBearingY = Top;
+ glyph->metrics2.vertAdvance = advance;
+
+ /* XXX: for now, we have no better algorithm for the lsb, but it */
+ /* should work fine. */
+ /* */
+ left = ( bbox.xMin - bbox.xMax ) / 2;
+
+ /* grid-fit them if necessary */
+ if ( IS_HINTED(loader->load_flags) )
+ {
+ left &= -64;
+ top = (top + 63) & -64;
+ advance = (advance + 32) & -64;
+ }
+
+ glyph->metrics.vertBearingX = left;
+ glyph->metrics.vertBearingY = top;
+ glyph->metrics.vertAdvance = advance;
+ }
+
+ /* Adjust advance width to the value contained in the hdmx table. */
+ if ( !face->postscript.isFixedPitch && size &&
+ IS_HINTED(loader->load_flags) )
+ {
+ FT_Byte* widths = Get_Advance_Widths( face,
+ size->root.metrics.x_ppem );
+ if ( widths )
+ glyph->metrics.horiAdvance = widths[glyph_index] << 6;
+ }
+
+ /* set glyph dimensions */
+ glyph->metrics.width = bbox.xMax - bbox.xMin;
+ glyph->metrics.height = bbox.yMax - bbox.yMin;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ LOCAL_FUNC
+ FT_Error TT_Load_Glyph( T2_Size size,
+ T2_GlyphSlot glyph,
+ FT_UShort glyph_index,
+ FT_UInt load_flags )
+ {
+ SFNT_Interface* sfnt;
+ T2_Face face;
+ FT_Stream stream;
+ FT_Memory memory;
+ FT_Error error;
+ T2_Loader loader;
+ FT_GlyphZone* zone;
+
+ face = (TT_Face)glyph->face;
+ sfnt = (SFNT_Interface*)face->sfnt;
+ stream = face->root.stream;
+ memory = face->root.memory;
+ error = 0;
+
+ if ( !size || (load_flags & FT_LOAD_NO_SCALE) ||
+ (load_flags & FT_LOAD_NO_RECURSE ))
+ {
+ size = NULL;
+ load_flags |= FT_LOAD_NO_SCALE |
+ FT_LOAD_NO_HINTING |
+ FT_LOAD_NO_BITMAP;
+ }
+
+ glyph->num_subglyphs = 0;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+ /*********************************************************************/
+ /* Try to load embedded bitmap if any */
+ if ( size && (load_flags & FT_LOAD_NO_BITMAP) == 0 && sfnt->load_sbits )
+ {
+ TT_SBit_Metrics metrics;
+
+ error = sfnt->load_sbit_image( face,
+ size->root.metrics.x_ppem,
+ size->root.metrics.y_ppem,
+ glyph_index,
+ load_flags,
+ stream,
+ &glyph->bitmap,
+ &metrics );
+ if ( !error )
+ {
+ glyph->outline.n_points = 0;
+ glyph->outline.n_contours = 0;
+
+ glyph->metrics.width = (FT_Pos)metrics.width << 6;
+ glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+ glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+ glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+ glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
+
+ glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+ glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+ glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
+
+ glyph->format = ft_glyph_format_bitmap;
+ return error;
+ }
+ }
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+ if ( load_flags & FT_LOAD_NO_OUTLINE )
+ return ( error ? error : TT_Err_Unavailable_Bitmap );
+
+ /* seek to the beginning of the glyph table. For Type 43 fonts */
+ /* the table might be accessed from a Postscript stream or something */
+ /* else... */
+ error = face->goto_table( face, TTAG_glyf, stream, 0 );
+ if (error)
+ {
+ FT_ERROR(( "TT.GLoad: could not access glyph table\n" ));
+ goto Exit;
+ }
+
+ MEM_Set( &loader, 0, sizeof(loader) );
+
+ /* update the glyph zone bounds */
+ zone = &((TT_Driver)face->root.driver)->zone;
+ error = FT_Update_GlyphZone( zone,
+ face->root.max_points,
+ face->root.max_contours );
+ if (error)
+ {
+ FT_ERROR(( "TT.GLoad: could not update loader glyph zone\n" ));
+ goto Exit;
+ }
+ loader.base = *zone;
+
+ loader.zone.n_points = 0;
+ loader.zone.n_contours = 0;
+
+ /* clear all outline flags, except the "owner" one */
+ glyph->outline.flags &= ft_outline_owner;
+
+ if (size && size->root.metrics.y_ppem < 24 )
+ glyph->outline.flags |= ft_outline_high_precision;
+
+ /************************************************************************/
+ /* let's initialise the rest of our loader now */
+ loader.left_points = face->root.max_points;
+ loader.left_contours = face->root.max_contours;
+ loader.load_flags = load_flags;
+
+ loader.face = face;
+ loader.size = size;
+ loader.glyph = glyph;
+ loader.stream = stream;
+
+ loader.glyf_offset = FILE_Pos();
+
+ /* Main loading loop */
+ glyph->format = ft_glyph_format_outline;
+ glyph->num_subglyphs = 0;
+ error = load_truetype_glyph( &loader, glyph_index );
+ if (!error)
+ compute_glyph_metrics( &loader, glyph_index );
+
+ Exit:
+ return error;
+ }
+
+
+
+/* END */
--- /dev/null
+++ b/src/cff/t2gload.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2load.c
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2load.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2objs.c
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2objs.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2parse.c
@@ -1,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;
+
+ }
+
+
+
+
+
--- /dev/null
+++ b/src/cff/t2parse.h
@@ -1,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 */
--- /dev/null
+++ b/src/cff/t2tokens.h
@@ -1,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 )
+