ref: f0df85ba2a573c6c5c602667e9f91ef3b00c1d20
parent: 9ca2af38384a3fc3a26cc7eae96c59ad08aca2b2
author: David Turner <[email protected]>
date: Wed Jun 21 20:17:42 EDT 2000
- MAJOR INTERNAL REDESIGN: A lot of internal modifications have been performed lately on the source in order to provide the following enhancements: - more generic module support: The FT_Module type is now defined to represent a handle to a given module. The file <freetype/ftmodule.h> contains the FT_Module_Class definition, as well as the module-loading public API The FT_Driver type is still defined, and still represents a pointer to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module, FT_Get_Driver by FT_Get_Module, etc.. - support for generic glyph image types: The FT_Renderer type is a pointer to a module used to perform various operations on glyph image. Each renderer is capable of handling images in a single format (e.g. ft_glyph_format_outline). Its functions are used to: - transform an glyph image - render a glyph image into a bitmap - return the control box (dimensions) of a given glyph image The scan converters "ftraster.c" and "ftgrays.c" have been moved to the new directory "src/renderer", and are used to provide two default renderer modules. One corresponds to the "standard" scan-converter, the other to the "smooth" one. The current renderer can be set through the new function FT_Set_Renderer. The old raster-related function FT_Set_Raster, FT_Get_Raster and FT_Set_Raster_Mode have now disappeared, in favor of the new: FT_Get_Renderer FT_Set_Renderer see the file <freetype/ftrender.h> for more details.. These changes were necessary to properly support different scalable formats in the future, like bi-color glyphs, etc.. - glyph loader object: A new internal object, called a 'glyph loader' has been introduced in the base layer. It is used by all scalable format font drivers to load glyphs and composites. This object has been created to reduce the code size of each driver, as each one of them basically re-implemented its functionality. See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for more information.. - FT_GlyphSlot had new fields: In order to support extended features (see below), the FT_GlyphSlot structure has a few new fields: linearHoriAdvance: this field gives the linearly scaled (i.e. scaled but unhinted) advance width for the glyph, expressed as a 16.16 fixed pixel value. This is useful to perform WYSIWYG text. linearVertAdvance: this field gives the linearly scaled advance height for the glyph (relevant in vertical glyph layouts only). This is useful to perform WYSIWYG text. Note that the two above field replace the removed "metrics2" field in the glyph slot. advance: this field is a vector that gives the transformed advance for the glyph. By default, it corresponds to the advance width, unless FT_LOAD_VERTICAL_LAYOUT was specified when calling FT_Load_Glyph or FT_Load_Char bitmap_left: this field gives the distance in integer pixels from the current pen position to the left-most pixel of a glyph image WHEN IT IS A BITMAP. It is only valid when the "format" field is set to "ft_glyph_format_bitmap", for example, after calling the new function FT_Render_Glyph. bitmap_top: this field gives the distance in integer pixels from the current pen position (located on the baseline) to the top-most pixel of the glyph image WHEN IT IS A BITMAP. Positive values correspond to upwards Y. loader: this is a new private field for the glyph slot. Client applications should not touch it.. - support for transforms and direct rendering in FT_Load_Glyph: Most of the functionality found in <freetype/ftglyph.h> has been moved to the core library. Hence, the following: - a transform can be specified for a face through FT_Set_Transform. this transform is applied by FT_Load_Glyph to scalable glyph images (i.e. NOT TO BITMAPS) before the function returns, unless the bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags.. - once a glyph image has been loaded, it can be directly converted to a bitmap by using the new FT_Render_Glyph function. Note that this function takes the glyph image from the glyph slot, and converts it to a bitmap whose properties are returned in "face.glyph.bitmap", "face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original native image might be lost after the conversion. - when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph and FT_Load_Char functions will call FT_Render_Glyph automatically when needed.
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,135 @@
LATEST CHANGES
+ - MAJOR INTERNAL REDESIGN:
+
+ A lot of internal modifications have been performed lately on the
+ source in order to provide the following enhancements:
+
+ - more generic module support:
+
+ The FT_Module type is now defined to represent a handle to a given
+ module. The file <freetype/ftmodule.h> contains the FT_Module_Class
+ definition, as well as the module-loading public API
+
+ The FT_Driver type is still defined, and still represents a pointer
+ to a font driver. Note that FT_Add_Driver is replaced by FT_Add_Module,
+ FT_Get_Driver by FT_Get_Module, etc..
+
+
+ - support for generic glyph image types:
+
+ The FT_Renderer type is a pointer to a module used to perform various
+ operations on glyph image.
+
+ Each renderer is capable of handling images in a single format
+ (e.g. ft_glyph_format_outline). Its functions are used to:
+
+ - transform an glyph image
+ - render a glyph image into a bitmap
+ - return the control box (dimensions) of a given glyph image
+
+
+ The scan converters "ftraster.c" and "ftgrays.c" have been moved
+ to the new directory "src/renderer", and are used to provide two
+ default renderer modules.
+
+ One corresponds to the "standard" scan-converter, the other to the
+ "smooth" one.
+
+ The current renderer can be set through the new function
+ FT_Set_Renderer.
+
+ The old raster-related function FT_Set_Raster, FT_Get_Raster and
+ FT_Set_Raster_Mode have now disappeared, in favor of the new:
+
+ FT_Get_Renderer
+ FT_Set_Renderer
+
+ see the file <freetype/ftrender.h> for more details..
+
+ These changes were necessary to properly support different scalable
+ formats in the future, like bi-color glyphs, etc..
+
+
+ - glyph loader object:
+
+ A new internal object, called a 'glyph loader' has been introduced
+ in the base layer. It is used by all scalable format font drivers
+ to load glyphs and composites.
+
+ This object has been created to reduce the code size of each driver,
+ as each one of them basically re-implemented its functionality.
+
+ See <freetype/internal/ftobjs.h> and the FT_GlyphLoader type for
+ more information..
+
+
+
+ - FT_GlyphSlot had new fields:
+
+ In order to support extended features (see below), the FT_GlyphSlot
+ structure has a few new fields:
+
+ linearHoriAdvance: this field gives the linearly scaled (i.e.
+ scaled but unhinted) advance width for the glyph,
+ expressed as a 16.16 fixed pixel value. This
+ is useful to perform WYSIWYG text.
+
+ linearVertAdvance: this field gives the linearly scaled advance
+ height for the glyph (relevant in vertical glyph
+ layouts only). This is useful to perform
+ WYSIWYG text.
+
+ Note that the two above field replace the removed "metrics2" field
+ in the glyph slot.
+
+ advance: this field is a vector that gives the transformed
+ advance for the glyph. By default, it corresponds
+ to the advance width, unless FT_LOAD_VERTICAL_LAYOUT
+ was specified when calling FT_Load_Glyph or FT_Load_Char
+
+ bitmap_left: this field gives the distance in integer pixels from
+ the current pen position to the left-most pixel of
+ a glyph image WHEN IT IS A BITMAP. It is only valid
+ when the "format" field is set to
+ "ft_glyph_format_bitmap", for example, after calling
+ the new function FT_Render_Glyph.
+
+ bitmap_top: this field gives the distance in integer pixels from
+ the current pen position (located on the baseline) to
+ the top-most pixel of the glyph image WHEN IT IS A
+ BITMAP. Positive values correspond to upwards Y.
+
+ loader: this is a new private field for the glyph slot. Client
+ applications should not touch it..
+
+
+ - support for transforms and direct rendering in FT_Load_Glyph:
+
+ Most of the functionality found in <freetype/ftglyph.h> has been
+ moved to the core library. Hence, the following:
+
+ - a transform can be specified for a face through FT_Set_Transform.
+ this transform is applied by FT_Load_Glyph to scalable glyph images
+ (i.e. NOT TO BITMAPS) before the function returns, unless the
+ bit flag FT_LOAD_IGNORE_TRANSFORM was set in the load flags..
+
+
+ - once a glyph image has been loaded, it can be directly converted to
+ a bitmap by using the new FT_Render_Glyph function. Note that this
+ function takes the glyph image from the glyph slot, and converts
+ it to a bitmap whose properties are returned in "face.glyph.bitmap",
+ "face.glyph.bitmap_left" and "face.glyph.bitmap_top". The original
+ native image might be lost after the conversion.
+
+
+ - when using the new bit flag FT_LOAD_RENDER, the FT_Load_Glyph
+ and FT_Load_Char functions will call FT_Render_Glyph automatically
+ when needed.
+
+
+
+
- reformated all modules source code in order to get rid of the basic
data types redifinitions (i.e. "TT_Int" instead of "FT_Int", "T1_Fixed"
instead of "FT_Fixed"). Hence the format-specific prefixes like "TT_",
--- a/config/modules.mk
+++ b/config/modules.mk
@@ -40,7 +40,7 @@
#
clean_module_list:
@-$(DELETE) $(subst $(SEP),$(HOSTSEP),$(FT_MODULE_LIST))
- @-echo Regenerating the font drivers list in $(FT_MODULE_LIST)...
+ @-echo Regenerating the modules list in $(FT_MODULE_LIST)...
make_module_list: clean_module_list
@echo done.
@@ -60,10 +60,10 @@
# $(OPEN_DRIVER) & $(CLOSE_DRIVER) are used to specify a given font driver
# in the `module.mk' rules file.
#
-OPEN_DRIVER := $(OPEN_MODULE)FT_DRIVER(
+OPEN_DRIVER := $(OPEN_MODULE)FT_USE_MODULE(
CLOSE_DRIVER := )$(CLOSE_MODULE)
-ECHO_DRIVER := @echo "* driver: #
+ECHO_DRIVER := @echo "* module: #
ECHO_DRIVER_DESC := (
ECHO_DRIVER_DONE := )"
--- a/demos/src/ftmulti.c
+++ b/demos/src/ftmulti.c
@@ -13,8 +13,7 @@
/****************************************************************************/
#include <freetype/freetype.h>
-#include <freetype/ftraster.h>
-#include <freetype/ftgrays.h>
+#include <freetype/ftrender.h>
#include <freetype/ftmm.h>
#include "common.h"
@@ -76,7 +75,8 @@
int use_grays = 1;
/* the standard raster's interface */
- FT_Raster_Funcs std_raster;
+ FT_Renderer std_renderer;
+ FT_Renderer smooth_renderer;
FT_Multi_Master multimaster;
FT_Long design_pos[T1_MAX_MM_AXIS];
@@ -460,10 +460,10 @@
static
void reset_raster( void )
{
- if ( antialias && use_grays )
- FT_Set_Raster( library, &ft_grays_raster );
+ if ( antialias && use_grays && smooth_renderer )
+ FT_Set_Renderer( library, smooth_renderer, 0, 0 );
else
- FT_Set_Raster( library, &std_raster );
+ FT_Set_Renderer( library, std_renderer, 0, 0 );
}
@@ -715,8 +715,11 @@
PanicZ( "Could not initialize FreeType library" );
/* retrieve the standard raster's interface */
- (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster );
- reset_raster();
+ std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
+ if (!std_renderer)
+ PanicZ( "Could not retrieve standard renderer" );
+
+ smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
NewFile:
ptsize = orig_ptsize;
--- a/demos/src/ftstring.c
+++ b/demos/src/ftstring.c
@@ -11,6 +11,7 @@
/****************************************************************************/
#include <freetype/freetype.h>
+#include <freetype/ftrender.h>
#include <freetype/ftglyph.h>
#include "common.h"
@@ -64,7 +65,8 @@
static int use_grays = 1;
/* the standard raster's interface */
- static FT_Raster_Funcs std_raster;
+ FT_Renderer std_renderer;
+ FT_Renderer smooth_renderer;
static FT_Matrix trans_matrix;
static int transform = 0;
@@ -470,14 +472,10 @@
static void reset_raster( void )
{
- FT_Error error;
-
- error = 1;
- if ( use_grays && antialias )
- error = FT_Set_Raster( library, &ft_grays_raster );
-
- if (error)
- (void)FT_Set_Raster( library, &std_raster );
+ if ( antialias && use_grays && smooth_renderer )
+ FT_Set_Renderer( library, smooth_renderer, 0, 0 );
+ else
+ FT_Set_Renderer( library, std_renderer, 0, 0 );
}
@@ -673,7 +671,11 @@
if (error) PanicZ( "Could not initialise FreeType library" );
/* retrieve the standard raster's interface */
- (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster );
+ std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
+ if (!std_renderer)
+ PanicZ( "Could not retrieve standard renderer" );
+
+ smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
NewFile:
ptsize = orig_ptsize;
--- a/demos/src/fttimer.c
+++ b/demos/src/fttimer.c
@@ -20,6 +20,7 @@
/****************************************************************************/
#include <freetype/freetype.h>
+#include <freetype/ftrender.h>
#include <stdio.h>
#include <stdlib.h>
@@ -331,8 +332,12 @@
/* set-up smooth anti-aliaser */
if (use_grays)
{
- error = FT_Set_Raster( library, &ft_grays_raster );
- if (error) Panic( "Could not initialize smooth anti-aliasing renderer" );
+ FT_Renderer smooth;
+
+ smooth = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
+ if (!smooth) Panic( "Could not initialize smooth anti-aliasing renderer" );
+
+ FT_Set_Renderer( library, smooth, 0, 0 );
}
/* Load face */
--- a/demos/src/ftview.c
+++ b/demos/src/ftview.c
@@ -17,8 +17,7 @@
#include <freetype/freetype.h>
-#include <freetype/ftraster.h>
-#include <freetype/ftgrays.h>
+#include <freetype/ftrender.h>
/* the following header shouldn't be used in normal programs */
#include <freetype/internal/ftdebug.h>
@@ -84,8 +83,10 @@
int trace_level = 0;
/* the standard raster's interface */
- FT_Raster_Funcs std_raster;
+ FT_Renderer std_renderer;
+ FT_Renderer smooth_renderer;
+
#define RASTER_BUFF_SIZE 32768
char raster_buff[RASTER_BUFF_SIZE];
@@ -458,10 +459,10 @@
static
void reset_raster( void )
{
- if ( antialias && use_grays )
- FT_Set_Raster( library, &ft_grays_raster );
+ if ( antialias && use_grays && smooth_renderer )
+ FT_Set_Renderer( library, smooth_renderer, 0, 0 );
else
- FT_Set_Raster( library, &std_raster );
+ FT_Set_Renderer( library, std_renderer, 0, 0 );
}
@@ -672,8 +673,12 @@
PanicZ( "Could not initialize FreeType library" );
/* retrieve the standard raster's interface */
- (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster );
+ std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
+ if (!std_renderer)
+ PanicZ( "Could not retrieve standard renderer" );
+ smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
+
NewFile:
ptsize = orig_ptsize;
hinted = 1;
--- a/demos/src/memtest.c
+++ b/demos/src/memtest.c
@@ -224,7 +224,7 @@
/* the new library has no drivers in it, add the default ones */
/* (implemented in ftinit.c).. */
- FT_Default_Drivers(library);
+ FT_Add_Default_Modules(library);
/* Now check all files */
--- a/demos/src/ttdebug.c
+++ b/demos/src/ttdebug.c
@@ -1203,7 +1203,7 @@
if (error) Panic( "could not initialise FreeType library" );
memory = library->memory;
- driver = FT_Get_Driver( library, "truetype" );
+ driver = (FT_Driver)FT_Get_Module( library, "truetype" );
if (!driver) Panic( "could not find the TrueType driver in FreeType 2\n" );
FT_Set_Debug_Hook( library,
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -1,7 +1,9 @@
-FT_DRIVER(cff_driver_interface)
-FT_DRIVER(t1cid_driver_interface)
-FT_DRIVER(psnames_driver_interface)
-FT_DRIVER(sfnt_driver_interface)
-FT_DRIVER(tt_driver_interface)
-FT_DRIVER(t1_driver_interface)
-FT_DRIVER(t1z_driver_interface)
+FT_USE_MODULE(cff_driver_class)
+FT_USE_MODULE(t1cid_driver_class)
+FT_USE_MODULE(psnames_module_class)
+FT_USE_MODULE(ft_standard_renderer_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(tt_driver_class)
+FT_USE_MODULE(t1_driver_class)
+FT_USE_MODULE(t1z_driver_class)
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -251,16 +251,12 @@
/*************************************************************************/
/* */
- /* FT_MAX_DRIVERS */
+ /* FT_MAX_MODULES */
/* */
- /* The maximum number of font drivers that can be registered in a */
- /* single FreeType library object. 8 seems to be a good choice due */
- /* to the relative low actual number of drivers ;-) */
+ /* The maximum number ofmodules that can be registered in a single */
+ /* FreeType library object. 16 seems to be a good choice for now :-) */
/* */
- /* If you don't intend to register new drivers at runtime, you */
- /* certainly do not need to change this value.. */
- /* */
-#define FT_MAX_DRIVERS 8
+#define FT_MAX_MODULES 16
/*************************************************************************/
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -212,6 +212,19 @@
/*************************************************************************/
/* */
/* <Type> */
+ /* FT_Module */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType module object. Each module can be */
+ /* a font driver, a renderer, or anything else that provides services */
+ /* to the formers.. */
+ /* */
+ typedef struct FT_ModuleRec_* FT_Module;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
/* FT_Driver */
/* */
/* <Description> */
@@ -225,9 +238,25 @@
typedef struct FT_DriverRec_* FT_Driver;
+
/*************************************************************************/
/* */
/* <Type> */
+ /* FT_Renderer */
+ /* */
+ /* <Description> */
+ /* A handle to a given FreeType renderer. A renderer is in charge */
+ /* of converting a glyph image to a bitmap, when necessary. Each */
+ /* supports a given glyph image format, and one or more target */
+ /* surface depths.. */
+ /* */
+ typedef struct FT_RendererRec_* FT_Renderer;
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
/* FT_Face */
/* */
/* <Description> */
@@ -607,7 +636,7 @@
/************************************************************/
/* The following fields should be considered private and */
- /* rarely, if ever, used by client applications.. */
+ /* rarely, if ever, used driectly by client applications.. */
FT_Driver driver;
FT_Memory memory;
@@ -750,6 +779,19 @@
#define FT_FACE_FLAG_MULTIPLE_MASTERS 0x100
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_FACE_FLAG_EXTERNAL_STREAM */
+ /* */
+ /* <Description> */
+ /* This bit field is used internally by FreeType to indicate that */
+ /* a face's stream was provided by the client application and should */
+ /* not be destroyed by FT_Done_Face */
+ /* */
+#define FT_FACE_FLAG_EXTERNAL_STREAM 0x4000
+
+
#define FT_HAS_HORIZONTAL(face) (face->face_flags & FT_FACE_FLAG_HORIZONTAL)
#define FT_HAS_VERTICAL(face) (face->face_flags & FT_FACE_FLAG_VERTICAL)
#define FT_HAS_KERNING(face) (face->face_flags & FT_FACE_FLAG_KERNING)
@@ -921,6 +963,25 @@
#define FT_SUBGLYPH_FLAG_USE_MY_METRICS 0x200
+ /**********************************************************************
+ *
+ * <Struct>
+ * FT_Glyph_Loader
+ *
+ * <Description>
+ * The glyph loader is an internal object used to load several
+ * glyphs together (for example, in the case of composites)
+ *
+ * <Note>
+ * the glyph loader implementation is not part of the high-level
+ * API, hence the forward structure declaration;
+ *
+ *
+ *********************************************************************/
+
+ typedef struct FT_GlyphLoader_ FT_GlyphLoader;
+
+
/*************************************************************************/
/* */
/* FreeType Glyph Slot base class */
@@ -941,36 +1002,105 @@
/* rare, the glyph slots are listed through a direct, */
/* single-linked list using its `next' field. */
/* */
+ /* generic :: A typeless pointer which is unused by the FreeType */
+ /* library or any of its drivers. It can be used by */
+ /* client applications to link their own data to each */
+ /* size object. */
+ /* */
/* metrics :: The metrics of the last loaded glyph in the slot. The */
/* returned values depend on the last load flags (see the */
/* FT_Load_Glyph() API function) and can be expressed */
/* either in 26.6 fractional pixels or font units. */
/* */
- /* metrics2 :: This field is used to return alternate glyph metrics */
- /* for scalable formats. Only four fields in it are */
- /* valid: horiBearingX, horiAdvance, vertBearingY and */
- /* vertAdvance. All other fields should be ignored. */
- /* By default, it contains the glyph metrics expressed */
- /* in font units. However, when FT_Load_Glyph() is called */
- /* with FT_LOAD_LINEAR set, the metrics are expressed */
- /* in 16.16 unhinted pixel values.. This can be useful */
- /* to perform WYSIWYG glyph layout.. */
+ /* Note that even when the glyph image is transformed, */
+ /* the metrics aren't.. */
/* */
- /* generic :: A typeless pointer which is unused by the FreeType */
- /* library or any of its drivers. It can be used by */
- /* client applications to link their own data to each */
- /* size object. */
+ /* linearHoriAdvance :: For scalable formats only, this field holds */
+ /* the linearly scaled horizontal advance width */
+ /* for the glyph (i.e. the scaled and unhinted */
+ /* value of the hori advance). This can be */
+ /* important to perform correct WYSIWYG layout */
/* */
- /* outline :: The outline descriptor for the current glyph, if it */
- /* is a vectorial one. The nature of the last loaded */
- /* glyph can be retrieved through the result value */
- /* returned by FT_Load_Glyph(). */
+ /* Note that this value is expressed by default */
+ /* in 16.16 pixels. However, when the glyph is */
+ /* loaded with the FT_LOAD_UNSCALED_LINEAR flag, */
+ /* this field contains simply the value of the */
+ /* advance in original font units. */
/* */
- /* bitmap :: The bitmap/graymap descriptor for the current glyph, */
- /* if it is a fixed-width one. The nature of the last */
- /* loaded glyph can be retrieved through the result value */
- /* returned by FT_Load_Glyph(). */
+ /* linearVertAdvance :: For scalable formats only, this field holds */
+ /* the linearly scaled vertical advance height */
+ /* for the glyph. See linearHoriAdvance for */
+ /* comments. */
/* */
+ /* advance :: this is the transformed advance width for the glyph */
+ /* */
+ /* format :: this field indicates the format of the image */
+ /* contained in the glyph slot. Typically */
+ /* ft_glyph_format_bitmap, ft_glyph_format_outline */
+ /* & ft_glyph_format_composite, but others are possible */
+ /* */
+ /* bitmap :: this field is used as a bitmap descriptor when the */
+ /* slot format is ft_glyph_format_bitmap. Note that */
+ /* the address and content of the bitmap buffer can */
+ /* change between calls of FT_Load_Glyph and a few */
+ /* other functions. */
+ /* */
+ /* bitmap_left :: this is the bitmap's left bearing expressed in */
+ /* integer pixels. Of course, this is only valid */
+ /* when the format is ft_glyph_format_bitmap */
+ /* */
+ /* bitmap_top :: this is the bitmap's top bearing expressed in */
+ /* integer pixels. Remember that this is the */
+ /* distance from the baseline to the top-most */
+ /* glyph scanline, upwards y coordinates being */
+ /* *positive* */
+ /* */
+ /* outline :: The outline descriptor for the current glyph image */
+ /* when it's format is ft_glyph_bitmap_outline. */
+ /* */
+ /* num_subglyphs :: the number of subglyphs in a composite glyph. */
+ /* this format is only valid for the composite */
+ /* glyph format, that should normally only be */
+ /* loaded with the FT_LOAD_NO_RECURSE flag.. */
+ /* */
+ /* subglyphs :: an array of subglyph descriptors for composite */
+ /* glyphs. There are 'num_subglyphs' elements in */
+ /* in there.. */
+ /* */
+ /* control_data :: certain font drivers can also return the control */
+ /* data for a given glyph image (e.g. TrueType */
+ /* bytecode, Type 1 charstrings, etc..). This field */
+ /* is a pointer to such data.. */
+ /* */
+ /* control_len :: this is the length in bytes of the control data */
+ /* */
+ /* other :: really wicked format can use this pointer to */
+ /* present their own glyph image to client apps. */
+ /* Note that the app will need to know about the */
+ /* image format, */
+ /* */
+ /* loader :: this is a private object for the glyph slot. Do */
+ /* not touch this.. */
+ /* */
+ /* <Note> */
+ /* When FT_Load_Glyph is called with default flags (FT_LOAD_DEFAULT), */
+ /* the glyph image is loaded in the glyph slot in its native format */
+ /* (e.g. a vectorial outline for TrueType and Type 1 formats) */
+ /* */
+ /* This image can later be converted into a bitmap by calling */
+ /* FT_Render_Glyph. This function finds the current renderer for the */
+ /* native image's format then invokes it. */
+ /* */
+ /* The renderer is in charge of transforming the native image through */
+ /* the slot's face transformation fields, then convert it into a */
+ /* bitmap that is returned in "slot->bitmap". */
+ /* */
+ /* Note that "slot->bitmap_left" and "slot->bitmap_top" are also */
+ /* used to specify the position of the bitmap relative to the current */
+ /* pen position (e.g. coordinates [0,0] on the baseline). Of course, */
+ /* "slot->format" is also changed to "ft_glyph_format_bitmap".. */
+ /* */
+ /* */
enum
{
@@ -977,21 +1107,29 @@
ft_glyph_own_bitmap = 1
};
+
+
typedef struct FT_GlyphSlotRec_
{
FT_Face face;
FT_GlyphSlot next;
FT_UInt flags;
+ FT_Generic generic;
FT_Glyph_Metrics metrics;
- FT_Glyph_Metrics metrics2;
+ FT_Fixed linearHoriAdvance;
+ FT_Fixed linearVertAdvance;
+ FT_Vector advance;
FT_Glyph_Format format;
+
FT_Bitmap bitmap;
+ FT_Int bitmap_left;
+ FT_Int bitmap_top;
+
FT_Outline outline;
- FT_Int num_subglyphs;
- FT_Int max_subglyphs;
+ FT_UInt num_subglyphs;
FT_SubGlyph* subglyphs;
void* control_data;
@@ -999,6 +1137,9 @@
void* other;
+ /* private fields */
+ FT_GlyphLoader* loader;
+
} FT_GlyphSlotRec;
@@ -1149,7 +1290,7 @@
FT_Long memory_size;
FT_String* pathname;
FT_Stream stream;
- FT_Driver driver;
+ FT_Module driver;
FT_Int num_params;
FT_Parameter* params;
@@ -1438,6 +1579,15 @@
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
+ /* <Note> */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the "face.glyph.advance" field, */
+ /* but **NOT** the values in "face.glyph.metrics".. */
+ /* */
FT_EXPORT_DEF(FT_Error) FT_Load_Glyph( FT_Face face,
FT_UInt glyph_index,
FT_Int load_flags );
@@ -1472,6 +1622,14 @@
/* is not defined in the charmap, this function will return an */
/* error.. */
/* */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the "face.glyph.advance" field, */
+ /* but **NOT** the values in "face.glyph.metrics".. */
+ /* */
FT_EXPORT_DEF(FT_Error) FT_Load_Char( FT_Face face,
FT_ULong char_code,
FT_Int load_flags );
@@ -1507,15 +1665,17 @@
/*************************************************************************/
/* */
/* <Constant> */
- /* FT_LOAD_NO_OUTLINE */
+ /* FT_LOAD_RENDER */
/* */
/* <Description> */
/* A bit-field constant, used with FT_Load_Glyph() to indicate that */
- /* the function should not load the vector outline of a given glyph. */
- /* If an embedded bitmap exists for the glyph in the font, it will be */
- /* loaded, otherwise nothing is returned and an error is produced. */
+ /* the function should load the glyph and immediately convert it */
+ /* into a bitmap, when necessary, by calling FT_Render_Glyph. */
/* */
-#define FT_LOAD_NO_OUTLINE 4
+ /* Note that by default, FT_Load_Glyph loads the glyph image in its */
+ /* native format.. */
+ /* */
+#define FT_LOAD_RENDER 4
/*************************************************************************/
@@ -1526,8 +1686,9 @@
/* <Description> */
/* A bit-field constant, used with FT_Load_Glyph() to indicate that */
/* the function should not load the bitmap or pixmap of a given */
- /* glyph. If an outline exists for the glyph in the font, it is */
- /* loaded, otherwise nothing is returned and an error is produced. */
+ /* glyph. This is useful when you do not want to load the embedded */
+ /* bitmaps of scalable formats, as the native glyph image will be */
+ /* loaded, and can then be renderer through FT_Render_Glyph */
/* */
#define FT_LOAD_NO_BITMAP 8
@@ -1535,16 +1696,19 @@
/*************************************************************************/
/* */
/* <Constant> */
- /* FT_LOAD_LINEAR */
+ /* FT_LOAD_VERTICAL_LAYOUT */
/* */
/* <Description> */
/* A bit-field constant, used with FT_Load_Glyph() to indicate that */
- /* the function should return the linearly scaled metrics for the */
- /* glyph in `slot->metrics2' (these metrics are not grid-fitted). */
- /* Otherwise, `metrics2' gives the original font units values. */
+ /* the glyph image should be prepared for vertical layout. This */
+ /* basically means that "face.glyph.advance" will correspond to the */
+ /* vertical advance height (instead of the default horizontal */
+ /* advance width), and that the glyph image will translated to */
+ /* match the vertical bearings positions.. */
/* */
-#define FT_LOAD_LINEAR 16
+#define FT_LOAD_VERTICAL_LAYOUT 16
+
/*************************************************************************/
/* */
/* <Constant> */
@@ -1557,6 +1721,7 @@
/* */
#define FT_LOAD_FORCE_AUTOHINT 32
+
/*************************************************************************/
/* */
/* <Constant> */
@@ -1571,6 +1736,7 @@
/* */
#define FT_LOAD_CROP_BITMAP 64
+
/*************************************************************************/
/* */
/* <Constant> */
@@ -1601,6 +1767,7 @@
/* */
#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH 512
+
/*************************************************************************/
/* */
/* <Constant> */
@@ -1621,9 +1788,52 @@
/* */
#define FT_LOAD_NO_RECURSE 1024
+
/*************************************************************************/
/* */
/* <Constant> */
+ /* FT_LOAD_IGNORE_TRANSFORM */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the glyph loader should not try to transform the loaded glyph */
+ /* image. */
+ /* */
+#define FT_LOAD_IGNORE_TRANSFORM 2048
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_ANTI_ALIAS */
+ /* */
+ /* <Description> */
+ /* Only used with FT_LOAD_RENDER set, indicates that the returned */
+ /* glyph image should be anti-aliased. This basically tells the */
+ /* glyph loader to use 'ft_render_mode_antialias' when calling */
+ /* FT_Render_Glyph. */
+ /* */
+ /* */
+#define FT_LOAD_LINEAR_ANTI_ALIAS 4096
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
+ /* FT_LOAD_LINEAR_DESIGN */
+ /* */
+ /* <Description> */
+ /* A bit-field constant, used with FT_Load_Glyph() to indicate that */
+ /* the function should return the linearly scaled metrics expressed */
+ /* in original font units, instead of the default 16.16 pixel values. */
+ /* */
+#define FT_LOAD_LINEAR_DESIGN 8192
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Constant> */
/* FT_LOAD_DEFAULT */
/* */
/* <Description> */
@@ -1638,6 +1848,69 @@
/*************************************************************************/
/* */
/* <Function> */
+ /* FT_Set_Transform */
+ /* */
+ /* <Description> */
+ /* A function used to set the transformation that is applied to glyph */
+ /* images just before they're converted to bitmaps in a glyph slot */
+ /* when FT_Render_Glyph is called.. */
+ /* */
+ /* <InOut> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
+ /* the identity matrix. */
+ /* delta :: A pointer to the translation vector. Use 0 for the null */
+ /* vector. */
+ /* */
+ /* <Note> */
+ /* The transformation is only applied to scalable image formats. */
+ /* */
+ FT_EXPORT_DEF( void ) FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta );
+
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Render_Glyph
+ *
+ * <Description>
+ * Converts a given glyph image to a bitmap. It does so by inspecting
+ * the glyph image format, find the relevant renderer, and invoke it
+ *
+ * <Input>
+ * slot :: handle to the glyph slot containing the image to
+ * convert
+ *
+ * render_mode :: a set of bit flags indicating which kind of bitmap
+ * to render. For now, only 'ft_render_mode_anti_alias'
+ * is supported by the available renderers, but others
+ * could appear later (e.g. LCD or TV optimised)
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ * <Note>
+ * in case of success, the renderer will be used to convert glyph
+ * images in the renderer's known format into bitmaps.
+ *
+ * This doesn't change the current renderer for other formats..
+ *
+ * The slot's native image should be considered lost after the
+ * conversion..
+ *
+ *************************************************************************/
+
+ FT_EXPORT_DEF(FT_Error) FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_UInt render_mode );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* FT_Get_Kerning */
/* */
/* <Description> */
@@ -1829,6 +2102,27 @@
/*************************************************************************/
/* */
/* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ FT_EXPORT_DEF(void) FT_Vector_Transform( FT_Vector* vector,
+ FT_Matrix* matrix );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
/* FT_Outline_Get_Bitmap */
/* */
/* <Description> */
@@ -1893,6 +2187,7 @@
FT_Outline* outline,
FT_Raster_Params* params );
+
/*************************************************************************/
/* */
/* <Function> */
@@ -2045,6 +2340,7 @@
FT_Pos yOffset );
+#if 0
/*************************************************************************/
/* */
/* <Function> */
@@ -2146,8 +2442,8 @@
FT_Glyph_Format format,
unsigned long mode,
void* args );
+#endif
-
/***************************************************************************/
/***************************************************************************/
/***************************************************************************/
@@ -2231,25 +2527,6 @@
FT_EXPORT_DEF(void) FT_Outline_Reverse( FT_Outline* outline );
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Vector_Transform */
- /* */
- /* <Description> */
- /* Transforms a single vector through a 2x2 matrix. */
- /* */
- /* <InOut> */
- /* vector :: The target vector to transform */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the source 2x2 matrix. */
- /* */
- /* <MT-Note> */
- /* Yes. */
- /* */
- FT_EXPORT_DEF(void) FT_Vector_Transform( FT_Vector* vector,
- FT_Matrix* matrix );
/*************************************************************************/
--- a/include/freetype/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -64,6 +64,8 @@
FT_ERRORDEF( FT_Err_Invalid_CharMap_Handle, 0x0035, "invalid charmap handle" )
FT_ERRORDEF( FT_Err_Invalid_Outline, 0x0036, "invalid outline" )
FT_ERRORDEF( FT_Err_Invalid_Dimensions, 0x0037, "invalid dimensions" )
+ FT_ERRORDEF( FT_Err_Invalid_Version, 0x0038, "invalid FreeType version" )
+ FT_ERRORDEF( FT_Err_Lower_Module_Version, 0x0039, "module version is too low" )
FT_ERRORDEF( FT_Err_Unavailable_Outline, 0x0040, "unavailable outline" )
FT_ERRORDEF( FT_Err_Unavailable_Bitmap, 0x0041, "unavailable bitmap" )
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -5,6 +5,9 @@
/* This file defines the glyph image formats recognized by FreeType, as */
/* well as the default raster interface. */
/* */
+/* Note: a "raster" is simply a scan-line converter, used to render */
+/* FT_Outlines into FT_Bitmaps */
+/* */
/* Copyright 1996-2000 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg */
/* */
@@ -187,6 +190,10 @@
* for paletted pixel modes.
*
* <Note>
+ * For now, the only pixel mode supported by FreeType are mono and grays.
+ * However, drivers might be added in the future to support more "colorful"
+ * options..
+ *
* When using pixel modes pal2, pal4 and pal8 with a void `palette'
* field, a gray pixmap with respectively 4, 16 and 256 levels of gray
* is assumed. This, in order to be compatible with some embedded bitmap
@@ -195,7 +202,6 @@
* Note that no font was found presenting such embedded bitmaps, so this
* is currently completely unhandled by the library.
*
- *
*************************************************************************/
typedef struct FT_Bitmap_
@@ -220,8 +226,7 @@
/* */
/* <Description> */
/* This structure is used to describe an outline to the scan-line */
- /* converter. It's a copy of the TT_Outline type that was defined */
- /* in FreeType 1.x. */
+ /* converter. */
/* */
/* <Fields> */
/* n_contours :: The number of contours in the outline. */
@@ -268,6 +273,7 @@
} FT_Outline;
+
/*************************************************************************/
/* */
/* <Enum> */
@@ -286,7 +292,7 @@
/* ft_outline_even_odd_fill :: */
/* by default, outlines are filled using the non-zero winding */
/* rule. When set to 1, the outline will be filled using the */
- /* even-odd fill rule.. (XXX: unimplemented) */
+ /* even-odd fill rule.. (only works with the smooth raster) */
/* */
/* ft_outline_reverse_fill :: */
/* By default, outside contours of an outline are oriented in */
@@ -460,6 +466,23 @@
/* conic_to :: The second-order Bezier arc emitter. */
/* cubic_to :: The third-order Bezier arc emitter. */
/* */
+ /* shift :: the shift that is applied to coordinates before */
+ /* they're sent to the emmiter */
+ /* */
+ /* delta :: the delta that is applied to coordinates before */
+ /* they're sent to the emitter, but after the shift */
+ /* */
+ /* <Note> */
+ /* The point coordinates sent to the emitters are the transformed */
+ /* version of the original coordinates (this is important for high */
+ /* accuracy during scan-conversion). The transform is simply: */
+ /* */
+ /* x' = (x << shift) - delta */
+ /* y' = (x << shift) - delta */
+ /* */
+ /* Set the value of 'shift' and 'delta' to 0 to get the original */
+ /* point coordinates.. */
+ /* */
typedef struct FT_Outline_Funcs_
{
FT_Outline_MoveTo_Func move_to;
@@ -479,13 +502,12 @@
/* FT_IMAGE_TAG */
/* */
/* <Description> */
- /* This macro converts four letter tags which are used to label */
- /* TrueType tables into an unsigned long to be used within FreeType. */
+ /* This macro converts four letter tags into unsigned longs.. */
/* */
#define FT_IMAGE_TAG( _x1, _x2, _x3, _x4 ) \
- (((unsigned long)_x1 << 24) | \
- ((unsigned long)_x2 << 16) | \
- ((unsigned long)_x3 << 8) | \
+ (((unsigned long)_x1 << 24) | \
+ ((unsigned long)_x2 << 16) | \
+ ((unsigned long)_x3 << 8) | \
(unsigned long)_x4)
@@ -495,7 +517,7 @@
* FT_Glyph_Format
*
* <Description>
- * An enumeration type used to describethe format of a given glyph
+ * An enumeration type used to describe the format of a given glyph
* image. Note that this version of FreeType only supports two image
* formats, even though future font drivers will be able to register
* their own format.
@@ -541,13 +563,13 @@
/**************************************************************************
*
+ * A raster is a scan converter, in charge of rendering an outline into a
+ * a bitmap. This section contains the public API for rasters.
*
+ * Note that in FreeType 2, all rasters are now encapsulated within
+ * specific modules called "renderers". See <freetype/internal/ftrender.h>
+ * for more details on renderers..
*
- *
- *
- *
- *
- *
**************************************************************************/
/*************************************************************************/
@@ -934,5 +956,4 @@
} FT_Raster_Funcs;
#endif /* FTIMAGE_H */
-
--- a/include/freetype/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
@@ -2,7 +2,7 @@
/* */
/* ftdriver.h */
/* */
-/* FreeType driver interface (specification). */
+/* FreeType font driver interface (specification). */
/* */
/* Copyright 1996-2000 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
@@ -18,174 +18,9 @@
#ifndef FTDRIVER_H
#define FTDRIVER_H
-#include <freetype/freetype.h>
+#include <freetype/ftmodule.h>
+#include <freetype/config/ftconfig.h>
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** D R I V E R S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_initDriver */
- /* */
- /* <Description> */
- /* A driver method used to create a new driver object for a given */
- /* format. */
- /* */
- /* <InOut> */
- /* driver :: A handle to the `new' driver object. The fields */
- /* `library', `system', and `lock' are already set when the */
- /* base layer calls this method. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- typedef FT_Error (*FTDriver_initDriver)( FT_Driver driver );
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_doneDriver */
- /* */
- /* <Description> */
- /* A driver method used to finalize a given driver object. Note that */
- /* all faces and resources for this driver have been released before */
- /* this call, and that this function should NOT destroy the driver */
- /* object. */
- /* */
- /* <InOut> */
- /* driver :: A handle to target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- typedef FT_Error (*FTDriver_doneDriver)( FT_Driver driver );
-
-
- typedef void (*FTDriver_Interface)( void );
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_getInterface */
- /* */
- /* <Description> */
- /* Each driver can provide one or more extensions to the base */
- /* FreeType API. These can be used to access format specific */
- /* features (e.g., all TrueType/OpenType resources share a common */
- /* file structure and common tables which can be accessed through the */
- /* `sfnt' interface), or more simply generic ones (e.g., the */
- /* `postscript names' interface which can be used to retrieve the */
- /* PostScript name of a given glyph index). */
- /* */
- /* <InOut> */
- /* driver :: A handle to a driver object. */
- /* */
- /* <Input> */
- /* interface :: A string designing the interface. Examples are */
- /* `sfnt', `post_names', `charmaps', etc. */
- /* */
- /* <Return> */
- /* A typeless pointer to the extension's interface (normally a table */
- /* of function pointers). Returns NULL if the requested extension */
- /* isn't available (i.e., wasn't compiled in the driver at build */
- /* time). */
- /* */
- typedef FTDriver_Interface (*FTDriver_getInterface)
- ( FT_Driver driver,
- const FT_String* interface );
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* FT_FormatInterface */
- /* */
- /* <Description> */
- /* A driver interface field whose value is a driver-specific */
- /* interface method table. This table contains entry points to */
- /* various functions that are strictly related to the driver's */
- /* format. */
- /* */
- typedef void* FT_FormatInterface;
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FT_Attach_Reader */
- /* */
- /* <Description> */
- /* This function is associated to the `attach_file' driver-specific */
- /* interface. It is used to read additional data for a given face */
- /* from another input stream/file. For example, it is used to */
- /* attach a Type 1 AFM file to a given Type 1 face. */
- /* */
- typedef FT_Error (*FT_Attach_Reader)( FT_Face face, FT_Stream stream );
-
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** F A C E S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_initFace */
- /* */
- /* <Description> */
- /* A driver method used to initialize a new face object. The object */
- /* must be created by the caller. */
- /* */
- /* <InOut> */
- /* stream :: The input stream. */
- /* face :: A handle to the new target face. */
- /* */
- /* <Input> */
- /* typeface_index :: The face index in the font resource. Used to */
- /* access individual faces in collections. */
- /* */
- /* num_params :: number of optional generic parameters */
- /* parameters :: table of generic parameters */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* The `typeface_index' parameter field will be set to -1 if the */
- /* engine only wants to test the format of the resource. This means */
- /* that font drivers should simply check the font format, then return */
- /* immediately with an error code of 0 (meaning success). The field */
- /* `num_faces' should be set. */
- /* */
- /* The generic parameters are a way to pass additional data to a */
- /* given font driver when creating a new face object. In most cases */
- /* they will be simply ignored.. */
- /* */
- /* FTDriver_doneFace() will be called subsequently, whatever the */
- /* result was. */
- /* */
typedef FT_Error (*FTDriver_initFace)( FT_Stream stream,
FT_Face face,
FT_Int typeface_index,
@@ -193,124 +28,21 @@
FT_Parameter* parameters );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_doneFace */
- /* */
- /* <Description> */
- /* A driver method used to finalize a given face object. This */
- /* function does NOT destroy the object, that is the responsibility */
- /* of the caller. */
- /* */
- /* <InOut> */
- /* face :: A handle to the target face object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
typedef void (*FTDriver_doneFace)( FT_Face face );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_getKerning */
- /* */
- /* <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 :: A pointer to 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 method. Other layouts, or more sophisticated */
- /* kernings are out of the scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
- typedef FT_Error (*FTDriver_getKerning)( FT_Face face,
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_Vector* kerning );
+ typedef FT_Error (*FTDriver_initSize)( FT_Size size );
+ typedef void (*FTDriver_doneSize)( FT_Size size );
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** S I Z E S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_initSize */
- /* */
- /* <Description> */
- /* A driver method used to initialize a new size object. The object */
- /* must be created by the caller. */
- /* */
- /* <InOut> */
- /* size :: A handle to the new size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function should return an error if the face's format isn't */
- /* scalable. */
- /* */
- typedef FT_Error (*FTDriver_initSize)( FT_Size size );
+ typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot );
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_setCharSizes */
- /* */
- /* <Description> */
- /* A driver method used to reset a size's character sizes (horizontal */
- /* and vertical) expressed in fractional points. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Input> */
- /* char_width :: The character width expressed in 26.6 */
- /* fractional points. */
- /* char_height :: The character height expressed in 26.6 */
- /* fractional points. */
- /* horz_resolution :: The horizontal resolution. */
- /* vert_resolution :: The vertical resolution. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function should always FAIL if the face format isn't */
- /* scalable! */
- /* */
+
typedef FT_Error (*FTDriver_setCharSizes)( FT_Size size,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
@@ -317,127 +49,10 @@
FT_UInt horz_resolution,
FT_UInt vert_resolution );
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_setPixelSizes */
- /* */
- /* <Description> */
- /* A driver method used to reset a size's character sizes (horizontal */
- /* and vertical) expressed in integer pixels. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Input> */
- /* pixel_width :: The character width expressed in 26.6 fractional */
- /* pixels. */
- /* pixel_height :: The character height expressed in 26.6 fractional */
- /* pixels. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function should work with all kinds of `size' objects, either */
- /* fixed or scalable ones. */
- /* */
typedef FT_Error (*FTDriver_setPixelSizes)( FT_Size size,
FT_UInt pixel_width,
FT_UInt pixel_height );
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_doneSize */
- /* */
- /* <Description> */
- /* A driver method used to finalize a given size object. This method */
- /* does NOT destroy the object; this is the responsibility of the */
- /* caller. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- typedef void (*FTDriver_doneSize)( FT_Size size );
-
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** G L Y P H S L O T S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_initGlyphSlot */
- /* */
- /* <Description> */
- /* A driver method used to initialize a new glyph slot object. The */
- /* object must be created by the caller. The glyph slot is a */
- /* container where a single glyph can be loaded, either in outline or */
- /* bitmap format. */
- /* */
- /* <InOut> */
- /* slot :: A handle to the new glyph slot object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- typedef FT_Error (*FTDriver_initGlyphSlot)( FT_GlyphSlot slot );
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_doneGlyphSlot */
- /* */
- /* <Description> */
- /* A driver method used to finalize a given glyph slot. The object */
- /* is not destroyed by this function. */
- /* */
- /* <InOut> */
- /* slot :: A handle to the new glyph slot object. */
- /* */
- typedef void (*FTDriver_doneGlyphSlot)( FT_GlyphSlot slot );
-
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_loadGlyph */
- /* */
- /* <Description> */
- /* A driver method used to load a glyph within a given glyph slot. */
- /* */
- /* <InOut> */
- /* slot :: A handle to 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. */
- /* */
- /* <Input> */
- /* 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). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
typedef FT_Error (*FTDriver_loadGlyph)( FT_GlyphSlot slot,
FT_Size size,
FT_UInt glyph_index,
@@ -444,149 +59,116 @@
FT_Int load_flags );
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** C H A R A C T E R M A P S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* <FuncType> */
- /* FTDriver_getCharIndex */
- /* */
- /* <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> */
- /* The glyph index. 0 means `undefined character code'. */
- /* */
typedef FT_UInt (*FTDriver_getCharIndex)( FT_CharMap charmap,
FT_Long charcode );
+ typedef FT_Error (*FTDriver_getKerning)( FT_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning );
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
- /**** I N T E R F A C E ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ typedef FT_Error (*FTDriver_attachFile)( FT_Face face, FT_Stream stream );
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* FT_DriverInterface */
- /* */
- /* <Description> */
- /* A structure which holds a font driver's basic interface used by */
- /* the high-level parts of FreeType (or other applications). */
- /* */
- /* Most scalable drivers provide a specialized interface to access */
- /* format specific features. It can be retrieved with a call to */
- /* `get_format_interface()', and should be defined in each font */
- /* driver header (e.g., ttdriver.h, t1driver.h, etc). */
- /* */
- /* All fields are function pointers. */
- /* */
- /* <Fields> */
- /* driver_object_size :: The size in bytes of a single driver */
- /* object. */
- /* face_object_size :: The size in bytes of a single face object. */
- /* size_object_size :: The size in bytes of a single size object. */
- /* slot_object_size :: The size in bytes of a single glyph slot */
- /* object. */
- /* */
- /* driver_name :: A string to describe the driver to the */
- /* system. It doesn't necessarily describe */
- /* in detail all the font formats the driver */
- /* may support. */
- /* driver_version :: The driver version number. Starts at 1. */
- /* driver_requires :: The FreeType major version this driver is */
- /* written for. This number should be equal */
- /* to or greater than 2! */
- /* */
- /* format_interface :: A pointer to the driver's format-specific */
- /* interface. */
- /* */
- /* init_driver :: Used to initialize a given driver object. */
- /* done_driver :: Used to finalize and destroy a given */
- /* driver object. */
- /* get_interface :: Returns an interface for a given driver */
- /* extension. */
- /* */
- /* init_face :: Initializes a given face object. */
- /* done_face :: Discards a face object, as well as all */
- /* child objects (sizes, charmaps, glyph */
- /* slots). */
- /* get_kerning :: Returns the kerning vector corresponding */
- /* to a pair of glyphs, expressed in unscaled */
- /* font units. */
- /* */
- /* init_size :: Initializes a given size object. */
- /* done_size :: Finalizes a given size object. */
- /* set_size_char_sizes :: Resets a scalable size object's character */
- /* size. */
- /* set_pixel_sizes :: Resets a face size object's pixel */
- /* dimensions. Applies to both scalable and */
- /* fixed faces. */
- /* */
- /* init_glyph_slot :: Initializes a given glyph slot object. */
- /* done_glyph_slot :: Finalizes a given glyph slot. */
- /* load_glyph :: Loads a given glyph into a given slot. */
- /* */
- /* get_char_index :: Returns the glyph index for a given */
- /* charmap. */
- /* */
- typedef struct FT_DriverInterface_
+
+ typedef FT_Error (*FTDriver_getAdvances)( FT_Face face,
+ FT_UInt first,
+ FT_UInt count,
+ FT_Bool vertical,
+ FT_UShort* advances );
+
+
+ /*************************************************************************
+ *
+ * <Struct>
+ * FT_Driver_Class
+ *
+ * <Description>
+ * The font driver class. This structure mostly contains pointers to
+ * driver methods.
+ *
+ * <Fields>
+ * face_object_size :: size of a face object in bytes
+ * size_object_size :: size of a size object in bytes
+ * slot_object_size :: size of a glyph object in bytes
+ *
+ * init_face :: format-specific face constructor
+ * done_face :: format-specific face destructor
+ *
+ * init_size :: format-specific size constructor
+ * done_size :: format-specific size destructor
+ *
+ * init_slot :: format-specific slot constructor
+ * done_slot :: format-specific slot destructor
+ *
+ * set_char_sizes :: handle to a function used to set the new character
+ * size in points + resolution. can be set to 0 to
+ * indicate default behaviour
+ *
+ * set_pixel_sizes :: handme to function used to set the new character
+ * size in pixels. can be set to 0 to indicate
+ * default behaviour
+ *
+ * load_glyph :: load a given glyph image in a slot. This field
+ * is mandatory !
+ *
+ * get_char_index :: return the glyph index of a given character
+ * for a given charmap. This field is mandatory !
+ *
+ * get_kerning :: return the unscaled kerning for a given pair
+ * of glyphs. can be set to 0 if the format doesn't
+ * support kerning.
+ *
+ * attach_file :: reads additional data for a face from another
+ * file/stream. For example, this can be used
+ * to add data from AFM or PFM files on a Type 1
+ * face, or a CIDMap on a CID-keyed face..
+ *
+ * get_advances :: a function used to return the advances of 'count'
+ * glyphs, starting at 'index'. the "vertical" flags
+ * must be set when vertical advances are queried.
+ * the advances buffer is caller-allocated
+ *
+ * get_bboxes :: a function used to return the bounding box of
+ * 'count' glyphs, starting at 'index'. the bbox
+ * buffer is caller-allocated
+ *
+ * <Note>
+ * Most function pointers, with the exception of "load_glyph" and
+ * "get_char_index" can be set to 0 to indicate a the default behaviour
+ *
+ *
+ *************************************************************************/
+
+ typedef struct FT_Driver_Class_
{
- FT_Int driver_object_size;
+ FT_Module_Class root;
+
FT_Int face_object_size;
FT_Int size_object_size;
FT_Int slot_object_size;
- FT_String* driver_name;
- FT_Int driver_version;
- FT_Int driver_requires;
-
- void* format_interface;
-
- FTDriver_initDriver init_driver;
- FTDriver_doneDriver done_driver;
- FTDriver_getInterface get_interface;
-
FTDriver_initFace init_face;
FTDriver_doneFace done_face;
- FTDriver_getKerning get_kerning;
-
+
FTDriver_initSize init_size;
FTDriver_doneSize done_size;
+
+ FTDriver_initGlyphSlot init_slot;
+ FTDriver_doneGlyphSlot done_slot;
+
FTDriver_setCharSizes set_char_sizes;
FTDriver_setPixelSizes set_pixel_sizes;
- FTDriver_initGlyphSlot init_glyph_slot;
- FTDriver_doneGlyphSlot done_glyph_slot;
FTDriver_loadGlyph load_glyph;
-
FTDriver_getCharIndex get_char_index;
- } FT_DriverInterface;
+ FTDriver_getKerning get_kerning;
+ FTDriver_attachFile attach_file;
+
+ FTDriver_getAdvances get_advances;
+
+ } FT_Driver_Class;
#endif /* FTDRIVER_H */
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -26,6 +26,7 @@
#define FTOBJS_H
#include <freetype/internal/ftmemory.h>
+#include <freetype/ftrender.h>
#include <freetype/internal/ftdriver.h>
/*************************************************************************/
@@ -67,12 +68,103 @@
#endif
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /************************************************************************
+ *
+ * <Struct>
+ * FT_ModuleRec
+ *
+ * <Description>
+ * A module object instance.
+ *
+ * <Fields>
+ * clazz :: pointer to module's class
+ * library :: handle to parent library object
+ * memory :: handle to memory manager
+ * generic :: generic structure for user-level extensibility (?)
+ *
+ ************************************************************************/
+
+ typedef struct FT_ModuleRec_
+ {
+ FT_Module_Class* clazz;
+ FT_Library library;
+ FT_Memory memory;
+ FT_Generic generic;
+
+ } FT_ModuleRec;
+
+ /* typecast an object to a FT_Module */
+ #define FT_MODULE(x) ((FT_Module)(x))
+ #define FT_MODULE_CLASS(x) FT_MODULE(x)->clazz
+ #define FT_MODULE_LIBRARY(x) FT_MODULE(x)->library
+ #define FT_MODULE_MEMORY(x) FT_MODULE(x)->memory
+
+ #define FT_MODULE_IS_DRIVER(x) (FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_font_driver )
+
+ #define FT_MODULE_IS_DRIVER(x) (FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_font_driver )
+
+ #define FT_MODULE_IS_RENDERER(x) (FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_renderer )
+
+ #define FT_DRIVER_IS_SCALABLE(x) (FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_driver_scalable )
+
+ #define FT_DRIVER_USES_OUTLINES(x) !(FT_MODULE_CLASS(x)->module_flags & \
+ ft_module_driver_no_outlines )
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* a few macros used to perform easy typecasts with minimal brain damage */
+
+ #define FT_FACE(x) ((FT_Face)x)
+ #define FT_SIZE(x) ((FT_Size)x)
+ #define FT_SLOT(x) ((FT_GlyphSlot)x)
+
+ #define FT_FACE_DRIVER(x) FT_FACE(x)->driver
+ #define FT_FACE_LIBRARY(x) FT_FACE_DRIVER(x)->root.library
+ #define FT_FACE_MEMORY(x) FT_FACE(x)->memory
+
+ #define FT_SIZE_FACE(x) FT_SIZE(x)->face
+ #define FT_SLOT_FACE(x) FT_SLOT(x)->face
+
+ #define FT_FACE_SLOT(x) FT_FACE(x)->glyph
+ #define FT_FACE_SIZE(x) FT_FACE(x)->size
+
+
+ /* this must be kept exported - this will be used later in our own */
+ /* high-level caching font manager called SemTex (way after the */
+ /* 2.0 release though.. */
FT_EXPORT_DEF(FT_Error) FT_New_Size( FT_Face face,
FT_Size* size );
FT_EXPORT_DEF(FT_Error) FT_Done_Size( FT_Size size );
+
FT_EXPORT_DEF(FT_Error) FT_New_GlyphSlot( FT_Face face,
FT_GlyphSlot* aslot );
@@ -80,13 +172,76 @@
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** G L Y P H L O A D E R ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ typedef struct FT_GlyphLoad_
+ {
+ FT_Outline outline; /* outline */
+ FT_UInt num_subglyphs; /* number of subglyphs */
+ FT_SubGlyph* subglyphs; /* subglyphs */
+ FT_Vector* extra_points; /* extra points table.. */
+
+ } FT_GlyphLoad;
+
+
+ struct FT_GlyphLoader_
+ {
+ FT_Memory memory;
+ FT_UInt max_points;
+ FT_UInt max_contours;
+ FT_UInt max_subglyphs;
+ FT_Bool use_extra;
+
+ FT_GlyphLoad base;
+ FT_GlyphLoad current;
+
+ void* other; /* for possible future extension ? */
+
+ };
+
+
+ BASE_DEF(FT_Error) FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader* *aloader );
+
+ BASE_DEF(FT_Error) FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader );
+
+ BASE_DEF(void) FT_GlyphLoader_Done( FT_GlyphLoader* loader );
+
+ BASE_DEF(void) FT_GlyphLoader_Reset( FT_GlyphLoader* loader );
+
+ BASE_DEF(void) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader );
+
+ BASE_DEF(FT_Error) FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
+ FT_UInt n_points,
+ FT_UInt n_contours );
+
+ BASE_DEF(FT_Error) FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
+ FT_UInt n_subs );
+
+ BASE_DEF(void) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader );
+
+
+ BASE_DEF(void) FT_GlyphLoader_Add( FT_GlyphLoader* loader );
+
+ BASE_DEF(FT_Error) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
+ FT_GlyphLoader* source );
+
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
- /**** D R I V E R S ****/
+ /**** R E N D E R E R S ****/
/**** ****/
/**** ****/
/*************************************************************************/
@@ -93,7 +248,39 @@
/*************************************************************************/
/*************************************************************************/
+ #define FT_RENDERER(x) ((FT_Renderer)(x))
+
+ typedef struct FT_RendererRec_
+ {
+ FT_ModuleRec root;
+ FT_Renderer_Class* clazz;
+ FT_Glyph_Format glyph_format;
+
+ FT_Raster raster;
+ FT_Raster_Render_Func raster_render;
+ FTRenderer_render render;
+
+ } FT_RendererRec;
+
/*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** F O N T D R I V E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* typecast a module into a driver easily */
+ #define FT_DRIVER(x) ((FT_Driver)(x))
+
+ /* typecast a module as a driver, and get its driver class */
+ #define FT_DRIVER_CLASS(x) FT_DRIVER(x)->clazz
+
+ /*************************************************************************/
/* */
/* <Struct> */
/* FT_DriverRec */
@@ -103,29 +290,12 @@
/* managing and loading font files of a given format. */
/* */
/* <Fields> */
- /* library :: A handle to the driver's parent library. */
+ /* root :: contains the fields of the root module class */
/* */
- /* memory :: A handle to the driver's memory object. This is a */
- /* duplicate of `library->memory'. */
+ /* clazz :: a pointer to the font driver's class. Note that */
+ /* this is NOT root.clazz. 'class' wasn't used */
+ /* as it's a reserved word in C++ */
/* */
- /* interface :: A set of driver methods that implement its */
- /* behaviour. These methods are called by the */
- /* various FreeType functions like FT_New_Face(), */
- /* FT_Load_Glyph(), etc. */
- /* */
- /* format :: A typeless pointer, used to store the address of */
- /* the driver's format specific interface. This is a */
- /* table of other driver methods that are specific to */
- /* its format. Format specific interfaces are */
- /* defined in the driver's header files (e.g., */
- /* `freetype/drivers/ttlib/ttdriver.h'). */
- /* */
- /* version :: The driver's version. It can be used for */
- /* versioning and dynamic driver update if needed. */
- /* */
- /* description :: An ASCII string describing the driver's supported */
- /* format, like `truetype', `type1', etc. */
- /* */
/* faces_list :: The list of faces currently opened by this driver. */
/* */
/* extensions :: a typeless pointer to the driver's extensions */
@@ -132,23 +302,19 @@
/* registry, when they are supported through the */
/* config macro FT_CONFIG_OPTION_EXTENSIONS */
/* */
+ /* glyph_loader :: glyph loader for all faces managed by this driver */
+ /* this object isn't defined for unscalable formats */
+ /* */
typedef struct FT_DriverRec_
{
- FT_Library library;
- FT_Memory memory;
+ FT_ModuleRec root;
+ FT_Driver_Class* clazz;
+
+ FT_ListRec faces_list;
+ void* extensions;
+
+ FT_GlyphLoader* glyph_loader;
- FT_Generic generic;
-
- FT_DriverInterface interface;
- FT_FormatInterface format;
-
- FT_Int version; /* driver version */
- FT_String* description; /* format description */
-
- FT_ListRec faces_list; /* driver's faces list */
-
- void* extensions;
-
} FT_DriverRec;
@@ -157,19 +323,6 @@
/*************************************************************************/
/**** ****/
/**** ****/
- /**** G L Y P H Z O N E S ****/
- /**** ****/
- /**** ****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /**** ****/
- /**** ****/
/**** L I B R A R I E S ****/
/**** ****/
/**** ****/
@@ -197,31 +350,45 @@
/* generic :: Client data variable. Used to extend the */
/* Library class by higher levels and clients. */
/* */
- /* num_drivers :: The number of drivers currently registered */
+ /* num_modules :: The number of modules currently registered */
/* within this library. This is set to 0 for new */
- /* libraries. New drivers are added through the */
- /* FT_Add_Driver() API function. */
+ /* libraries. New modules are added through the */
+ /* FT_Add_Module() API function. */
/* */
- /* drivers :: A table used to store handles to the currently */
- /* registered font drivers. Note that each driver */
+ /* modules :: A table used to store handles to the currently */
+ /* registered modules. Note that each font driver */
/* contains a list of its opened faces. */
/* */
+ /* renderers :: the list of renderers currently registered */
+ /* within the library. */
+ /* */
+ /* cur_renderer :: current outline renderer. This is a short cut */
+ /* used to avoid parsing the list on each call to */
+ /* FT_Outline_Render. It is a handle to the current */
+ /* renderer for the ft_glyph_format_outline format. */
+ /* */
/* raster_pool :: The raster object's render pool. This can */
/* ideally be changed dynamically at run-time. */
/* */
+ /* raster_pool_size :: size of the render pool in bytes */
+ /* */
+ /* */
+ /* */
+ /* */
typedef void (*FT_DebugHook_Func)( void* arg );
+
typedef struct FT_LibraryRec_
{
- FT_Memory memory; /* library's memory object */
+ FT_Memory memory; /* library's memory manager */
FT_Generic generic;
- FT_Int num_drivers;
- FT_Driver drivers[ FT_MAX_DRIVERS ]; /* driver objects */
+ FT_Int num_modules;
+ FT_Module modules[ FT_MAX_MODULES ]; /* module objects */
- FT_Raster_Funcs raster_funcs[ FT_MAX_GLYPH_FORMATS ];
- FT_Raster rasters [ FT_MAX_GLYPH_FORMATS ];
+ FT_ListRec renderers; /* list of renderers */
+ FT_Renderer cur_renderer; /* current outline renderer */
void* raster_pool; /* scan-line conversion render pool */
long raster_pool_size; /* size of render pool in bytes */
@@ -239,21 +406,13 @@
- FT_EXPORT_DEF(void) FT_Set_Debug_Hook( FT_Library library,
- FT_UInt hook_index,
- FT_DebugHook_Func debug_hook );
+ FT_EXPORT_DEF(void) FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook );
- FT_EXPORT_DEF(FT_Error) FT_Add_Driver( FT_Library library,
- const FT_DriverInterface* driver_interface );
- FT_EXPORT_DEF(FT_Error) FT_Remove_Driver( FT_Driver driver );
-
-
- FT_EXPORT_DEF(FT_Driver) FT_Get_Driver( FT_Library library,
- char* driver_name );
-
#ifndef FT_CONFIG_OPTION_NO_DEFAULT_SYSTEM
FT_EXPORT_DEF(FT_Error) FT_New_Stream( const char* filepathname,
@@ -264,6 +423,7 @@
FT_EXPORT_DEF(FT_Memory) FT_New_Memory( void );
#endif
+
/* Define default raster's interface. The default raster is located in `src/base/ftraster.c' */
/* */
--- a/include/freetype/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -110,8 +110,8 @@
typedef
- FTDriver_Interface (*SFNT_Get_Interface_Func)( FT_Driver driver,
- const char* interface );
+ FT_Module_Interface (*SFNT_Get_Interface_Func)( FT_Module module,
+ const char* interface );
/*************************************************************************/
--- a/src/base/ftextend.c
+++ b/src/base/ftextend.c
@@ -70,7 +70,7 @@
FT_Extension_Registry* registry;
- memory = driver->library->memory;
+ memory = driver->root.library->memory;
if ( ALLOC( registry, sizeof ( *registry ) ) )
return error;
@@ -101,7 +101,7 @@
LOCAL_FUNC
FT_Error FT_Done_Extensions( FT_Driver driver )
{
- FT_Memory memory = driver->memory;
+ FT_Memory memory = driver->root.memory;
FREE( driver->extensions );
@@ -126,7 +126,7 @@
/* */
FT_EXPORT_FUNC( FT_Error ) FT_Register_Extension(
FT_Driver driver,
- FT_Extension_Class* class )
+ FT_Extension_Class* clazz )
{
FT_Extension_Registry* registry;
@@ -134,7 +134,7 @@
if ( !driver )
return FT_Err_Invalid_Driver_Handle;
- if ( !class )
+ if ( !clazz )
return FT_Err_Invalid_Argument;
registry = (FT_Extension_Registry*)driver->extensions;
@@ -143,11 +143,10 @@
FT_Int n = registry->num_extensions;
FT_Extension_Class* cur = registry->classes + n;
-
if ( n >= FT_MAX_EXTENSIONS )
return FT_Err_Too_Many_Extensions;
- *cur = *class;
+ *cur = *clazz;
cur->offset = registry->cur_offset;
@@ -260,7 +259,7 @@
cur->finalize( ext, face );
}
- memory = face->driver->memory;
+ memory = face->driver->root.memory;
FREE( face->extensions );
}
@@ -302,7 +301,7 @@
if ( !registry )
return FT_Err_Ok;
- memory = face->driver->memory;
+ memory = face->driver->root.memory;
if ( ALLOC( face->extensions, registry->cur_offset ) )
return error;
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -209,11 +209,9 @@
/* transform the outline -- note that the original metrics are NOT */
/* transformed by this, only the outline points themselves... */
- FT_Outline_Transform( &face->glyph->outline,
- &face->transform_matrix );
FT_Outline_Translate( &face->glyph->outline,
- face->transform_delta.x + origin_x,
- face->transform_delta.y + origin_y );
+ origin_x,
+ origin_y );
/* compute the size in pixels of the outline */
FT_Outline_Get_CBox( &face->glyph->outline, &cbox );
@@ -257,7 +255,7 @@
FT_Outline_Translate( &face->glyph->outline,
-cbox.xMin,
-cbox.yMin );
- error = FT_Outline_Get_Bitmap( face->driver->library,
+ error = FT_Outline_Get_Bitmap( face->driver->root.library,
&face->glyph->outline,
&bitglyph->bitmap );
if ( error )
@@ -327,8 +325,8 @@
*vecglyph = 0;
- /* check that NO_OUTLINE and NO_RECURSE are not set */
- if ( load_flags & ( FT_LOAD_NO_OUTLINE | FT_LOAD_NO_RECURSE ) )
+ /* check that RENDER and NO_RECURSE are not set */
+ if ( load_flags & ( FT_LOAD_RENDER | FT_LOAD_NO_RECURSE ) )
{
error = FT_Err_Invalid_Argument;
goto Exit;
@@ -348,16 +346,6 @@
goto Exit;
}
- /* transform the outline -- note that the original metrics are NOT */
- /* transformed by this, only the outline points themselves... */
- if ( face->transform_flags )
- {
- FT_Outline_Transform( &face->glyph->outline, &face->transform_matrix );
- FT_Outline_Translate( &face->glyph->outline,
- face->transform_delta.x,
- face->transform_delta.y );
- }
-
/* now, create a new outline glyph and copy everything */
memory = face->memory;
if ( ALLOC( glyph, sizeof ( *glyph ) ) )
@@ -366,7 +354,7 @@
ft_prepare_glyph( (FT_Glyph)glyph, face, 0 );
glyph->metrics.glyph_type = ft_glyph_type_outline;
- error = FT_Outline_New( face->driver->library,
+ error = FT_Outline_New( face->driver->root.library,
face->glyph->outline.n_points,
face->glyph->outline.n_contours,
&glyph->outline );
@@ -383,72 +371,6 @@
Fail:
FREE( glyph );
goto Exit;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Transform */
- /* */
- /* <Description> */
- /* A function used to set the transformation that is applied to glyph */
- /* images just after they are loaded in the face's glyph slot, and */
- /* before they are returned by either FT_Get_Glyph_Bitmap() or */
- /* FT_Get_Glyph_Outline(). */
- /* */
- /* <InOut> */
- /* face :: A handle to the source face object. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
- /* the identity matrix. */
- /* delta :: A pointer to the translation vector. Use 0 for the null */
- /* vector. */
- /* */
- /* <Note> */
- /* The transformation is only applied to glyph outlines if they are */
- /* found in a font face. It is unable to transform embedded glyph */
- /* bitmaps. */
- /* */
- FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
- FT_Matrix* matrix,
- FT_Vector* delta )
- {
- if ( !face )
- return;
-
- face->transform_flags = 0;
-
- if ( !matrix )
- {
- face->transform_matrix.xx = 0x10000L;
- face->transform_matrix.xy = 0L;
- face->transform_matrix.yx = 0L;
- face->transform_matrix.yy = 0x10000L;
- matrix = &face->transform_matrix;
- }
- else
- face->transform_matrix = *matrix;
-
- /* set transform_flags bit flag 0 if `matrix' isn't the identity */
- if ( ( matrix->xy | matrix->yx ) ||
- matrix->xx != 0x10000L ||
- matrix->yy != 0x10000L )
- face->transform_flags |= 1;
-
- if ( !delta )
- {
- face->transform_delta.x = 0;
- face->transform_delta.y = 0;
- delta = &face->transform_delta;
- }
- else
- face->transform_delta = *delta;
-
- /* set transform_flags bit flag 1 if `delta' isn't the null vector */
- if ( delta->x | delta->y )
- face->transform_flags |= 2;
}
--- a/src/base/ftgrays.c
+++ /dev/null
@@ -1,1952 +1,0 @@
-/***************************************************************************/
-/* */
-/* ftgrays.c */
-/* */
-/* A new `perfect' anti-aliasing renderer (body). */
-/* */
-/* Copyright 2000 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This file can be compiled without the rest of the FreeType engine, */
- /* by defining the _STANDALONE_ macro when compiling it. You also need */
- /* to put the files `ftgrays.h' and `ftimage.h' into the current */
- /* compilation directory. Typically, you could do something like */
- /* */
- /* - copy `src/base/ftgrays.c' to your current directory */
- /* */
- /* - copy `include/freetype/ftimage.h' and */
- /* `include/freetype/ftgrays.h' to the same directory */
- /* */
- /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
- /* */
- /* cc -c -D_STANDALONE_ ftgrays.c */
- /* */
- /* The renderer can be initialized with a call to */
- /* `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */
- /* generated with a call to `ft_grays_raster.grays_raster_render'. */
- /* */
- /* See the comments and documentation in the file `ftimage.h' for */
- /* more details on how the raster works. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This is a new anti-aliasing scan-converter for FreeType 2. The */
- /* algorithm used here is _very_ different from the one in the standard */
- /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
- /* coverage of the outline on each pixel cell. */
- /* */
- /* It is based on ideas that I initially found in Raph Levien's */
- /* excellent LibArt graphics library (see http://www.levien.com/libart */
- /* for more information, though the web pages do not tell anything */
- /* about the renderer; you'll have to dive into the source code to */
- /* understand how it works). */
- /* */
- /* Note, however, that this is a _very_ different implementation */
- /* compared Raph's. Coverage information is stored in a very different */
- /* way, and I don't use sorted vector paths. Also, it doesn't use */
- /* floating point values. */
- /* */
- /* This renderer has the following advantages: */
- /* */
- /* - It doesn't need an intermediate bitmap. Instead, one can supply */
- /* a callback function that will be called by the renderer to draw */
- /* gray spans on any target surface. You can thus do direct */
- /* composition on any kind of bitmap, provided that you give the */
- /* renderer the right callback. */
- /* */
- /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
- /* each pixel cell */
- /* */
- /* - It performs a single pass on the outline (the `standard' FT2 */
- /* renderer makes two passes). */
- /* */
- /* - It can easily be modified to render to _any_ number of gray levels */
- /* cheaply. */
- /* */
- /* - For small (< 20) pixel sizes, it is faster than the standard */
- /* renderer. */
- /* */
- /*************************************************************************/
-
-
-#include <string.h> /* for memcpy() */
-
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_aaraster
-
-
-#define ErrRaster_Invalid_Outline -1
-
-
-#ifdef _STANDALONE_
-
-
-#include "ftimage.h"
-#include "ftgrays.h"
-
- /* This macro is used to indicate that a function parameter is unused. */
- /* Its purpose is simply to reduce compiler warnings. Note also that */
- /* simply defining it as `(void)x' doesn't avoid warnings with certain */
- /* ANSI compilers (e.g. LCC). */
-#define UNUSED( x ) (x) = (x)
-
- /* Disable the tracing mechanism for simplicity -- developers can */
- /* activate it easily by redefining these two macros. */
-#ifndef FT_ERROR
-#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-#ifndef FT_TRACE
-#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-
-#else /* _STANDALONE_ */
-
-
-#include <freetype/ftgrays.h>
-#include <freetype/internal/ftobjs.h> /* for UNUSED() */
-#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
-#include <freetype/freetype.h> /* for FT_Outline_Decompose() */
-
-
-#endif /* _STANDALONE_ */
-
-
- /* define this to dump debugging information */
-#define xxxDEBUG_GRAYS
-
- /* as usual, for the speed hungry :-) */
-
-#ifndef FT_STATIC_RASTER
-
-
-#define RAS_ARG PRaster raster
-#define RAS_ARG_ PRaster raster,
-
-#define RAS_VAR raster
-#define RAS_VAR_ raster,
-
-#define ras (*raster)
-
-
-#else /* FT_STATIC_RASTER */
-
-
-#define RAS_ARG /* empty */
-#define RAS_ARG_ /* empty */
-#define RAS_VAR /* empty */
-#define RAS_VAR_ /* empty */
-
- static TRaster ras;
-
-
-#endif /* FT_STATIC_RASTER */
-
-
- /* must be at least 6 bits! */
-#define PIXEL_BITS 8
-
-#define ONE_PIXEL ( 1L << PIXEL_BITS )
-#define PIXEL_MASK ( -1L << PIXEL_BITS )
-#define TRUNC( x ) ( (x) >> PIXEL_BITS )
-#define SUBPIXELS( x ) ( (x) << PIXEL_BITS )
-#define FLOOR( x ) ( (x) & -ONE_PIXEL )
-#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
-#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
-
-#if PIXEL_BITS >= 6
-#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
-#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
-#else
-#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
-#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
-#endif
-
- /* Define this if you want to use a more compact storage scheme. This */
- /* increases the number of cells available in the render pool but slows */
- /* down the rendering a bit. It is useful if you have a really tiny */
- /* render pool. */
-#define xxxGRAYS_COMPACT
-
-
- /*************************************************************************/
- /* */
- /* TYPE DEFINITIONS */
- /* */
- typedef int TScan; /* integer scanline/pixel coordinate */
- typedef long TPos; /* sub-pixel coordinate */
-
- /* maximal number of gray spans in a call to the span callback */
-#define FT_MAX_GRAY_SPANS 32
-
-
-#ifdef GRAYS_COMPACT
-
- typedef struct TCell_
- {
- short x : 14;
- short y : 14;
- int cover : PIXEL_BITS + 2;
- int area : PIXEL_BITS * 2 + 2;
-
- } TCell, *PCell;
-
-#else /* GRAYS_COMPACT */
-
- typedef struct TCell_
- {
- TScan x;
- TScan y;
- int cover;
- int area;
-
- } TCell, *PCell;
-
-#endif /* GRAYS_COMPACT */
-
-
- typedef struct TRaster_
- {
- PCell cells;
- int max_cells;
- int num_cells;
-
- TScan min_ex, max_ex;
- TScan min_ey, max_ey;
-
- int area;
- int cover;
- int invalid;
-
- TScan ex, ey;
- TScan cx, cy;
- TPos x, y;
-
- TScan last_ey;
-
- FT_Vector bez_stack[32 * 3];
- int lev_stack[32];
-
- FT_Outline outline;
- FT_Bitmap target;
-
- FT_Span gray_spans[FT_MAX_GRAY_SPANS];
- int num_gray_spans;
-
- FT_Raster_Span_Func render_span;
- void* render_span_data;
- int span_y;
-
- int band_size;
- int band_shoot;
- int conic_level;
- int cubic_level;
-
- void* memory;
-
- } TRaster, *PRaster;
-
-
- /*************************************************************************/
- /* */
- /* Initialize the cells table. */
- /* */
- static
- void init_cells( RAS_ARG_ void* buffer,
- long byte_size )
- {
- ras.cells = (PCell)buffer;
- ras.max_cells = byte_size / sizeof ( TCell );
- ras.num_cells = 0;
- ras.area = 0;
- ras.cover = 0;
- ras.invalid = 1;
- }
-
-
- /*************************************************************************/
- /* */
- /* Compute the outline bounding box. */
- /* */
- static
- void compute_cbox( RAS_ARG_ FT_Outline* outline )
- {
- FT_Vector* vec = outline->points;
- FT_Vector* limit = vec + outline->n_points;
-
-
- if ( outline->n_points <= 0 )
- {
- ras.min_ex = ras.max_ex = 0;
- ras.min_ey = ras.max_ey = 0;
- return;
- }
-
- ras.min_ex = ras.max_ex = vec->x;
- ras.min_ey = ras.max_ey = vec->y;
-
- vec++;
-
- for ( ; vec < limit; vec++ )
- {
- TPos x = vec->x;
- TPos y = vec->y;
-
-
- if ( x < ras.min_ex ) ras.min_ex = x;
- if ( x > ras.max_ex ) ras.max_ex = x;
- if ( y < ras.min_ey ) ras.min_ey = y;
- if ( y > ras.max_ey ) ras.max_ey = y;
- }
-
- /* truncate the bounding box to integer pixels */
- ras.min_ex = ras.min_ex >> 6;
- ras.min_ey = ras.min_ey >> 6;
- ras.max_ex = ( ras.max_ex + 63 ) >> 6;
- ras.max_ey = ( ras.max_ey + 63 ) >> 6;
- }
-
-
- /*************************************************************************/
- /* */
- /* Record the current cell in the table. */
- /* */
- static
- int record_cell( RAS_ARG )
- {
- PCell cell;
-
-
- if ( !ras.invalid && ( ras.area | ras.cover ) )
- {
- if ( ras.num_cells >= ras.max_cells )
- return 1;
-
- cell = ras.cells + ras.num_cells++;
- cell->x = ras.ex - ras.min_ex;
- cell->y = ras.ey - ras.min_ey;
- cell->area = ras.area;
- cell->cover = ras.cover;
- }
-
- return 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* Set the current cell to a new position. */
- /* */
- static
- int set_cell( RAS_ARG_ TScan ex,
- TScan ey )
- {
- int invalid, record, clean;
-
-
- /* Move the cell pointer to a new position. We set the `invalid' */
- /* flag to indicate that the cell isn't part of those we're interested */
- /* in during the render phase. This means that: */
- /* */
- /* . the new vertical position must be within min_ey..max_ey - 1. */
- /* . the new horizontal position must be strictly less than max_ex */
- /* */
- /* Note that if a cell is to the left of the clipping region, it is */
- /* actually set to the (min_ex-1) horizontal position. */
-
- record = 0;
- clean = 1;
-
- invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
- if ( !invalid )
- {
- /* All cells that are on the left of the clipping region go to the */
- /* min_ex - 1 horizontal position. */
- if ( ex < ras.min_ex )
- ex = ras.min_ex - 1;
-
- /* if our position is new, then record the previous cell */
- if ( ex != ras.ex || ey != ras.ey )
- record = 1;
- else
- clean = ras.invalid; /* do not clean if we didn't move from */
- /* a valid cell */
- }
-
- /* record the previous cell if needed (i.e., if we changed the cell */
- /* position, of changed the `invalid' flag) */
- if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) )
- return 1;
-
- if ( clean )
- {
- ras.area = 0;
- ras.cover = 0;
- }
-
- ras.invalid = invalid;
- ras.ex = ex;
- ras.ey = ey;
- return 0;
- }
-
-
- /*************************************************************************/
- /* */
- /* Start a new contour at a given cell. */
- /* */
- static
- void start_cell( RAS_ARG_ TScan ex,
- TScan ey )
- {
- if ( ex < ras.min_ex )
- ex = ras.min_ex - 1;
-
- ras.area = 0;
- ras.cover = 0;
- ras.ex = ex;
- ras.ey = ey;
- ras.last_ey = SUBPIXELS( ey );
- ras.invalid = 0;
-
- (void)set_cell( RAS_VAR_ ex, ey );
- }
-
-
- /*************************************************************************/
- /* */
- /* Render a scanline as one or more cells. */
- /* */
- static
- int render_scanline( RAS_ARG_ TScan ey,
- TPos x1,
- TScan y1,
- TPos x2,
- TScan y2 )
- {
- TScan ex1, ex2, fx1, fx2, delta;
- long p, first, dx;
- int incr, lift, mod, rem;
-
-
- dx = x2 - x1;
-
- ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
- ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
- fx1 = x1 - SUBPIXELS( ex1 );
- fx2 = x2 - SUBPIXELS( ex2 );
-
- /* trivial case. Happens often */
- if ( y1 == y2 )
- return set_cell( RAS_VAR_ ex2, ey );
-
- /* everything is located in a single cell. That is easy! */
- /* */
- if ( ex1 == ex2 )
- {
- delta = y2 - y1;
- ras.area += ( fx1 + fx2 ) * delta;
- ras.cover += delta;
- return 0;
- }
-
- /* ok, we'll have to render a run of adjacent cells on the same */
- /* scanline... */
- /* */
- p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
- first = ONE_PIXEL;
- incr = 1;
-
- if ( dx < 0 )
- {
- p = fx1 * ( y2 - y1 );
- first = 0;
- incr = -1;
- dx = -dx;
- }
-
- delta = p / dx;
- mod = p % dx;
- if ( mod < 0 )
- {
- delta--;
- mod += dx;
- }
-
- ras.area += ( fx1 + first ) * delta;
- ras.cover += delta;
-
- ex1 += incr;
- if ( set_cell( RAS_VAR_ ex1, ey ) )
- goto Error;
- y1 += delta;
-
- if ( ex1 != ex2 )
- {
- p = ONE_PIXEL * ( y2 - y1 );
- lift = p / dx;
- rem = p % dx;
- if ( rem < 0 )
- {
- lift--;
- rem += dx;
- }
-
- mod -= dx;
-
- while ( ex1 != ex2 )
- {
- delta = lift;
- mod += rem;
- if ( mod >= 0 )
- {
- mod -= dx;
- delta++;
- }
-
- ras.area += ONE_PIXEL * delta;
- ras.cover += delta;
- y1 += delta;
- ex1 += incr;
- if ( set_cell( RAS_VAR_ ex1, ey ) )
- goto Error;
- }
- }
-
- delta = y2 - y1;
- ras.area += ( fx2 + ONE_PIXEL - first ) * delta;
- ras.cover += delta;
-
- return 0;
-
- Error:
- return 1;
- }
-
-
- /*************************************************************************/
- /* */
- /* Render a given line as a series of scanlines. */
- /* */
- static
- int render_line( RAS_ARG_ TPos to_x,
- TPos to_y )
- {
- TScan ey1, ey2, fy1, fy2;
- TPos dx, dy, x, x2;
- int p, rem, mod, lift, delta, first, incr;
-
-
- ey1 = TRUNC( ras.last_ey );
- ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
- fy1 = ras.y - ras.last_ey;
- fy2 = to_y - SUBPIXELS( ey2 );
-
- dx = to_x - ras.x;
- dy = to_y - ras.y;
-
- /* we should do something about the trivial case where dx == 0, */
- /* as it happens very often! XXXXX */
-
- /* perform vertical clipping */
- {
- TScan min, max;
-
-
- min = ey1;
- max = ey2;
- if ( ey1 > ey2 )
- {
- min = ey2;
- max = ey1;
- }
- if ( min >= ras.max_ey || max < ras.min_ey )
- goto End;
- }
-
- /* everything is on a single scanline */
- if ( ey1 == ey2 )
- {
- if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) )
- goto Error;
- goto End;
- }
-
- /* ok, we'll have to render several scanlines */
- p = ( ONE_PIXEL - fy1 ) * dx;
- first = ONE_PIXEL;
- incr = 1;
-
- if ( dy < 0 )
- {
- p = fy1 * dx;
- first = 0;
- incr = -1;
- dy = -dy;
- }
-
- delta = p / dy;
- mod = p % dy;
- if ( mod < 0 )
- {
- delta--;
- mod += dy;
- }
-
- x = ras.x + delta;
- if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) )
- goto Error;
-
- ey1 += incr;
- if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
- goto Error;
-
- if ( ey1 != ey2 )
- {
- p = ONE_PIXEL * dx;
- lift = p / dy;
- rem = p % dy;
- if ( rem < 0 )
- {
- lift--;
- rem += dy;
- }
- mod -= dy;
-
- while ( ey1 != ey2 )
- {
- delta = lift;
- mod += rem;
- if ( mod >= 0 )
- {
- mod -= dy;
- delta++;
- }
-
- x2 = x + delta;
- if ( render_scanline( RAS_VAR_ ey1,
- x, ONE_PIXEL - first, x2, first ) )
- goto Error;
- x = x2;
- ey1 += incr;
- if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
- goto Error;
- }
- }
-
- if ( render_scanline( RAS_VAR_ ey1,
- x, ONE_PIXEL - first, to_x, fy2 ) )
- goto Error;
-
- End:
- ras.x = to_x;
- ras.y = to_y;
- ras.last_ey = SUBPIXELS( ey2 );
-
- return 0;
-
- Error:
- return 1;
- }
-
-
- static
- void split_conic( FT_Vector* base )
- {
- TPos a, b;
-
-
- base[4].x = base[2].x;
- b = base[1].x;
- a = base[3].x = ( base[2].x + b ) / 2;
- b = base[1].x = ( base[0].x + b ) / 2;
- base[2].x = ( a + b ) / 2;
-
- base[4].y = base[2].y;
- b = base[1].y;
- a = base[3].y = ( base[2].y + b ) / 2;
- b = base[1].y = ( base[0].y + b ) / 2;
- base[2].y = ( a + b ) / 2;
- }
-
-
- static
- int render_conic( RAS_ARG_ FT_Vector* control,
- FT_Vector* to )
- {
- TPos dx, dy;
- int top, level;
- int* levels;
- FT_Vector* arc;
-
-
- dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
-
- level = 1;
- dx = dx / ras.conic_level;
- while ( dx > 0 )
- {
- dx >>= 1;
- level++;
- }
-
- /* a shortcut to speed things up */
- if ( level <= 1 )
- {
- /* we compute the mid-point directly in order to avoid */
- /* calling split_conic() */
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
- mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
- return render_line( RAS_VAR_ mid_x, mid_y ) ||
- render_line( RAS_VAR_ to_x, to_y );
- }
-
- arc = ras.bez_stack;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
-
- arc[0].x = UPSCALE( to->x );
- arc[0].y = UPSCALE( to->y );
- arc[1].x = UPSCALE( control->x );
- arc[1].y = UPSCALE( control->y );
- arc[2].x = ras.x;
- arc[2].y = ras.y;
-
- while ( top >= 0 )
- {
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
-
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
-
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
-
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
- goto Draw;
-
- split_conic( arc );
- arc += 2;
- top++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
- }
-
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
- mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
- if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
- render_line( RAS_VAR_ to_x, to_y ) )
- return 1;
-
- top--;
- arc -= 2;
- }
- }
- return 0;
- }
-
-
- static
- void split_cubic( FT_Vector* base )
- {
- TPos a, b, c, d;
-
-
- base[6].x = base[3].x;
- c = base[1].x;
- d = base[2].x;
- base[1].x = a = ( base[0].x + c ) / 2;
- base[5].x = b = ( base[3].x + d ) / 2;
- c = ( c + d ) / 2;
- base[2].x = a = ( a + c ) / 2;
- base[4].x = b = ( b + c ) / 2;
- base[3].x = ( a + b ) / 2;
-
- base[6].y = base[3].y;
- c = base[1].y;
- d = base[2].y;
- base[1].y = a = ( base[0].y + c ) / 2;
- base[5].y = b = ( base[3].y + d ) / 2;
- c = ( c + d ) / 2;
- base[2].y = a = ( a + c ) / 2;
- base[4].y = b = ( b + c ) / 2;
- base[3].y = ( a + b ) / 2;
- }
-
-
- static
- int render_cubic( RAS_ARG_ FT_Vector* control1,
- FT_Vector* control2,
- FT_Vector* to )
- {
- TPos dx, dy, da, db;
- int top, level;
- int* levels;
- FT_Vector* arc;
-
-
- dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- da = dx;
-
- dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- db = dx;
-
- level = 1;
- da = da / ras.cubic_level;
- db = db / ras.conic_level;
- while ( da > 0 || db > 0 )
- {
- da >>= 1;
- db >>= 2;
- level++;
- }
-
- if ( level <= 1 )
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x +
- 3 * UPSCALE( control1->x + control2->x ) ) / 8;
- mid_y = ( ras.y + to_y +
- 3 * UPSCALE( control1->y + control2->y ) ) / 8;
-
- return render_line( RAS_VAR_ mid_x, mid_y ) ||
- render_line( RAS_VAR_ to_x, to_y );
- }
-
- arc = ras.bez_stack;
- arc[0].x = UPSCALE( to->x );
- arc[0].y = UPSCALE( to->y );
- arc[1].x = UPSCALE( control2->x );
- arc[1].y = UPSCALE( control2->y );
- arc[2].x = UPSCALE( control1->x );
- arc[2].y = UPSCALE( control1->y );
- arc[3].x = ras.x;
- arc[3].y = ras.y;
-
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
-
- while ( top >= 0 )
- {
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[3].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
- goto Draw;
- split_cubic( arc );
- arc += 3;
- top ++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
- }
-
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
- mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
-
- if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
- render_line( RAS_VAR_ to_x, to_y ) )
- return 1;
- top --;
- arc -= 3;
- }
- }
- return 0;
- }
-
-
- /* a macro comparing two cell pointers. Returns true if a <= b. */
-#if 1
-#define PACK( a ) ( ( (long)(a)->y << 16 ) + (a)->x )
-#define LESS_THAN( a, b ) ( PACK( a ) < PACK( b ) )
-#else /* 1 */
-#define LESS_THAN( a, b ) ( (a)->y < (b)->y || \
- ( (a)->y == (b)->y && (a)->x < (b)->x ) )
-#endif /* 1 */
-
-#define SWAP_CELLS( a, b, temp ) do \
- { \
- temp = *(a); \
- *(a) = *(b); \
- *(b) = temp; \
- } while ( 0 )
-#define DEBUG_SORT
-#define QUICK_SORT
-
-#ifdef SHELL_SORT
-
- /* A simple shell sort algorithm that works directly on our */
- /* cells table.. */
- static
- void shell_sort ( PCell cells,
- int count )
- {
- PCell i, j, limit = cells + count;
- TCell temp;
- int gap;
-
-
- /* compute initial gap */
- for ( gap = 0; ++gap < count; gap *= 3 )
- ;
-
- while ( gap /= 3 )
- {
- for ( i = cells + gap; i < limit; i++ )
- {
- for ( j = i - gap; ; j -= gap )
- {
- PCell k = j + gap;
-
-
- if ( LESS_THAN( j, k ) )
- break;
-
- SWAP_CELLS( j, k, temp );
-
- if ( j < cells + gap )
- break;
- }
- }
- }
- }
-
-#endif /* SHELL_SORT */
-
-
-#ifdef QUICK_SORT
-
- /* This is a non-recursive quicksort that directly process our cells */
- /* array. It should be faster than calling the stdlib qsort(), and we */
- /* can even tailor our insertion threshold... */
-
-#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */
- /* through a normal insertion sort.. */
-
- static
- void quick_sort( PCell cells,
- int count )
- {
- PCell stack[40]; /* should be enough ;-) */
- PCell* top; /* top of stack */
- PCell base, limit;
- TCell temp;
-
-
- limit = cells + count;
- base = cells;
- top = stack;
-
- for (;;)
- {
- int len = limit - base;
- PCell i, j, pivot;
-
-
- if ( len > QSORT_THRESHOLD )
- {
- /* we use base + len/2 as the pivot */
- pivot = base + len / 2;
- SWAP_CELLS( base, pivot, temp );
-
- i = base + 1;
- j = limit - 1;
-
- /* now ensure that *i <= *base <= *j */
- if ( LESS_THAN( j, i ) )
- SWAP_CELLS( i, j, temp );
-
- if ( LESS_THAN( base, i ) )
- SWAP_CELLS( base, i, temp );
-
- if ( LESS_THAN( j, base ) )
- SWAP_CELLS( base, j, temp );
-
- for (;;)
- {
- do i++; while ( LESS_THAN( i, base ) );
- do j--; while ( LESS_THAN( base, j ) );
-
- if ( i > j )
- break;
-
- SWAP_CELLS( i, j, temp );
- }
-
- SWAP_CELLS( base, j, temp );
-
- /* now, push the largest sub-array */
- if ( j - base > limit - i )
- {
- top[0] = base;
- top[1] = j;
- base = i;
- }
- else
- {
- top[0] = i;
- top[1] = limit;
- limit = j;
- }
- top += 2;
- }
- else
- {
- /* the sub-array is small, perform insertion sort */
- j = base;
- i = j + 1;
-
- for ( ; i < limit; j = i, i++ )
- {
- for ( ; LESS_THAN( j + 1, j ); j-- )
- {
- SWAP_CELLS( j + 1, j, temp );
- if ( j == base )
- break;
- }
- }
- if ( top > stack )
- {
- top -= 2;
- base = top[0];
- limit = top[1];
- }
- else
- break;
- }
- }
- }
-
-#endif /* QUICK_SORT */
-
-
-#ifdef DEBUG_GRAYS
-#ifdef DEBUG_SORT
-
- static
- int check_sort( PCell cells,
- int count )
- {
- PCell p, q;
-
-
- for ( p = cells + count - 2; p >= cells; p-- )
- {
- q = p + 1;
- if ( !LESS_THAN( p, q ) )
- return 0;
- }
- return 1;
- }
-
-#endif /* DEBUG_SORT */
-#endif /* DEBUG_GRAYS */
-
-
- static
- int Move_To( FT_Vector* to,
- FT_Raster raster )
- {
- TPos x, y;
-
-
- /* record current cell, if any */
- record_cell( (PRaster)raster );
-
- /* start to a new position */
- x = UPSCALE( to->x );
- y = UPSCALE( to->y );
- start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
- ((PRaster)raster)->x = x;
- ((PRaster)raster)->y = y;
- return 0;
- }
-
-
- static
- int Line_To( FT_Vector* to,
- FT_Raster raster )
- {
- return render_line( (PRaster)raster,
- UPSCALE( to->x ), UPSCALE( to->y ) );
- }
-
-
- static
- int Conic_To( FT_Vector* control,
- FT_Vector* to,
- FT_Raster raster )
- {
- return render_conic( (PRaster)raster, control, to );
- }
-
-
- static
- int Cubic_To( FT_Vector* control1,
- FT_Vector* control2,
- FT_Vector* to,
- FT_Raster raster )
- {
- return render_cubic( (PRaster)raster, control1, control2, to );
- }
-
-
- static
- void grays_render_span( int y,
- int count,
- FT_Span* spans,
- PRaster raster )
- {
- unsigned char* p;
- FT_Bitmap* map = &raster->target;
-
-
- /* first of all, compute the scanline offset */
- p = (unsigned char*)map->buffer - y * map->pitch;
- if ( map->pitch >= 0 )
- p += ( map->rows - 1 ) * map->pitch;
-
- for ( ; count > 0; count--, spans++ )
- {
- if ( spans->coverage )
-#if 1
- memset( p + spans->x, (unsigned char)spans->coverage, spans->len );
-#else /* 1 */
- {
- q = p + spans->x;
- limit = q + spans->len;
- for ( ; q < limit; q++ )
- q[0] = (unsigned char)spans->coverage;
- }
-#endif /* 1 */
- }
- }
-
-
-#ifdef DEBUG_GRAYS
-
-#include <stdio.h>
-
- static
- void dump_cells( RAS_ARG )
- {
- PCell cell, limit;
- int y = -1;
-
-
- cell = ras.cells;
- limit = cell + ras.num_cells;
-
- for ( ; cell < limit; cell++ )
- {
- if ( cell->y != y )
- {
- fprintf( stderr, "\n%2d: ", cell->y );
- y = cell->y;
- }
- fprintf( stderr, "[%d %d %d]",
- cell->x, cell->area, cell->cover );
- }
- fprintf(stderr, "\n" );
- }
-
-#endif /* DEBUG_GRAYS */
-
-
- static
- void grays_hline( RAS_ARG_ TScan x,
- TScan y,
- TPos area,
- int acount )
- {
- FT_Span* span;
- int count;
- int coverage;
-
-
- /* compute the coverage line's coverage, depending on the */
- /* outline fill rule */
- /* */
- /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
- /* */
- coverage = area >> ( PIXEL_BITS * 2 + 1 - 8); /* use range 0..256 */
-
- if ( ras.outline.flags & ft_outline_even_odd_fill )
- {
- if ( coverage < 0 )
- coverage = -coverage;
-
- while ( coverage >= 512 )
- coverage -= 512;
-
- if ( coverage > 256 )
- coverage = 512 - coverage;
- else if ( coverage == 256 )
- coverage = 255;
- }
- else
- {
- /* normal non-zero winding rule */
- if ( coverage < 0 )
- coverage = -coverage;
-
- if ( coverage >= 256 )
- coverage = 255;
- }
-
- y += ras.min_ey;
- x += ras.min_ex;
-
- if ( coverage )
- {
- /* see if we can add this span to the current list */
- count = ras.num_gray_spans;
- span = ras.gray_spans + count - 1;
- if ( count > 0 &&
- ras.span_y == y &&
- (int)span->x + span->len == (int)x &&
- span->coverage == coverage )
- {
- span->len += acount;
- return;
- }
-
- if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
- {
- if ( ras.render_span )
- ras.render_span( ras.span_y, count, ras.gray_spans,
- ras.render_span_data );
- /* ras.render_span( span->y, ras.gray_spans, count ); */
-
-#ifdef DEBUG_GRAYS
-
- if ( ras.span_y >= 0 )
- {
- int n;
-
-
- fprintf( stderr, "y=%3d ", ras.span_y );
- span = ras.gray_spans;
- for ( n = 0; n < count; n++, span++ )
- fprintf( stderr, "[%d..%d]:%02x ",
- span->x, span->x + span->len - 1, span->coverage );
- fprintf( stderr, "\n" );
- }
-
-#endif /* DEBUG_GRAYS */
-
- ras.num_gray_spans = 0;
- ras.span_y = y;
-
- count = 0;
- span = ras.gray_spans;
- }
- else
- span++;
-
- /* add a gray span to the current list */
- span->x = (short)x;
- span->len = (unsigned short)acount;
- span->coverage = (unsigned char)coverage;
- ras.num_gray_spans++;
- }
- }
-
-
- static
- void grays_sweep( RAS_ARG_ FT_Bitmap* target )
- {
- TScan x, y, cover, area;
- PCell start, cur, limit;
-
- UNUSED( target );
-
-
- cur = ras.cells;
- limit = cur + ras.num_cells;
-
- cover = 0;
- ras.span_y = -1;
- ras.num_gray_spans = 0;
-
- for (;;)
- {
- start = cur;
- y = start->y;
- x = start->x;
-
- area = start->area;
- cover += start->cover;
-
- /* accumulate all start cells */
- for (;;)
- {
- ++cur;
- if ( cur >= limit || cur->y != start->y || cur->x != start->x )
- break;
-
- area += cur->area;
- cover += cur->cover;
- }
-
- /* if the start cell has a non-null area, we must draw an */
- /* individual gray pixel there */
- if ( area && x >= 0 )
- {
- grays_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
- x++;
- }
-
- if ( x < 0 )
- x = 0;
-
- if ( cur < limit && start->y == cur->y )
- {
- /* draw a gray span between the start cell and the current one */
- if ( cur->x > x )
- grays_hline( RAS_VAR_ x, y,
- cover * ( ONE_PIXEL * 2 ), cur->x - x );
- }
- else
- {
- /* draw a gray span until the end of the clipping region */
- if ( cover && x < ras.max_ex - ras.min_ex )
- grays_hline( RAS_VAR_ x, y,
- cover * ( ONE_PIXEL * 2 ),
- ras.max_ex - x - ras.min_ex );
- cover = 0;
- }
-
- if ( cur >= limit )
- break;
- }
-
- if ( ras.render_span && ras.num_gray_spans > 0 )
- ras.render_span( ras.span_y, ras.num_gray_spans,
- ras.gray_spans, ras.render_span_data );
-
-#ifdef DEBUG_GRAYS
-
- {
- int n;
- FT_Span* span;
-
-
- fprintf( stderr, "y=%3d ", ras.span_y );
- span = ras.gray_spans;
- for ( n = 0; n < ras.num_gray_spans; n++, span++ )
- fprintf( stderr, "[%d..%d]:%02x ",
- span->x, span->x + span->len - 1, span->coverage );
- fprintf( stderr, "\n" );
- }
-
-#endif /* DEBUG_GRAYS */
-
- }
-
-
-#ifdef _STANDALONE_
-
- /*************************************************************************/
- /* */
- /* The following function should only compile in stand_alone mode, */
- /* i.e., when building this component without the rest of FreeType. */
- /* */
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Outline_Decompose */
- /* */
- /* <Description> */
- /* Walks over an outline's structure to decompose it into individual */
- /* segments and Bezier arcs. This function is also able to emit */
- /* `move to' and `close to' operations to indicate the start and end */
- /* of new contours in the outline. */
- /* */
- /* <Input> */
- /* outline :: A pointer to the source target. */
- /* */
- /* interface :: A table of `emitters', i.e,. function pointers called */
- /* during decomposition to indicate path operations. */
- /* */
- /* user :: A typeless pointer which is passed to each emitter */
- /* during the decomposition. It can be used to store */
- /* the state during the decomposition. */
- /* */
- /* <Return> */
- /* Error code. 0 means sucess. */
- /* */
- static
- int FT_Outline_Decompose( FT_Outline* outline,
- FT_Outline_Funcs* interface,
- void* user )
- {
-#undef SCALED
-#define SCALED( x ) ( ( (x) << shift ) - delta )
-
- FT_Vector v_last;
- FT_Vector v_control;
- FT_Vector v_start;
-
- FT_Vector* point;
- FT_Vector* limit;
- char* tags;
-
- int n; /* index of contour in outline */
- int first; /* index of first point in contour */
- int error;
- char tag; /* current point's state */
-
- int shift = interface->shift;
- FT_Pos delta = interface->delta;
-
-
- first = 0;
-
- for ( n = 0; n < outline->n_contours; n++ )
- {
- int last; /* index of last point in contour */
-
-
- last = outline->contours[n];
- limit = outline->points + last;
-
- v_start = outline->points[first];
- v_last = outline->points[last];
-
- v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
- v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
-
- v_control = v_start;
-
- point = outline->points + first;
- tags = outline->tags + first;
- tag = FT_CURVE_TAG( tags[0] );
-
- /* A contour cannot start with a cubic control point! */
- if ( tag == FT_Curve_Tag_Cubic )
- goto Invalid_Outline;
-
- /* check first point to determine origin */
- if ( tag == FT_Curve_Tag_Conic )
- {
- /* first point is conic control. Yes, this happens. */
- if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
- {
- /* start at last point if it is on the curve */
- v_start = v_last;
- limit--;
- }
- else
- {
- /* if both first and last points are conic, */
- /* start at their middle and record its position */
- /* for closure */
- v_start.x = ( v_start.x + v_last.x ) / 2;
- v_start.y = ( v_start.y + v_last.y ) / 2;
-
- v_last = v_start;
- }
- point--;
- tags--;
- }
-
- error = interface->move_to( &v_start, user );
- if ( error )
- goto Exit;
-
- while ( point < limit )
- {
- point++;
- tags++;
-
- tag = FT_CURVE_TAG( tags[0] );
- switch ( tag )
- {
- case FT_Curve_Tag_On: /* emit a single line_to */
- {
- FT_Vector vec;
-
-
- vec.x = SCALED( point->x );
- vec.y = SCALED( point->y );
-
- error = interface->line_to( &vec, user );
- if ( error )
- goto Exit;
- continue;
- }
-
- case FT_Curve_Tag_Conic: /* consume conic arcs */
- {
- v_control.x = SCALED( point->x );
- v_control.y = SCALED( point->y );
-
- Do_Conic:
- if ( point < limit )
- {
- FT_Vector vec;
- FT_Vector v_middle;
-
-
- point++;
- tags++;
- tag = FT_CURVE_TAG( tags[0] );
-
- vec.x = SCALED( point->x );
- vec.y = SCALED( point->y );
-
- if ( tag == FT_Curve_Tag_On )
- {
- error = interface->conic_to( &v_control, &vec, user );
- if ( error )
- goto Exit;
- continue;
- }
-
- if ( tag != FT_Curve_Tag_Conic )
- goto Invalid_Outline;
-
- v_middle.x = ( v_control.x + vec.x ) / 2;
- v_middle.y = ( v_control.y + vec.y ) / 2;
-
- error = interface->conic_to( &v_control, &v_middle, user );
- if ( error )
- goto Exit;
-
- v_control = vec;
- goto Do_Conic;
- }
-
- error = interface->conic_to( &v_control, &v_start, user );
- goto Close;
- }
-
- default: /* FT_Curve_Tag_Cubic */
- {
- FT_Vector vec1, vec2;
-
-
- if ( point + 1 > limit ||
- FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
- goto Invalid_Outline;
-
- point += 2;
- tags += 2;
-
- vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
- vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
-
- if ( point <= limit )
- {
- FT_Vector vec;
-
-
- vec.x = SCALED( point->x );
- vec.y = SCALED( point->y );
-
- error = interface->cubic_to( &vec1, &vec2, &vec, user );
- if ( error )
- goto Exit;
- continue;
- }
-
- error = interface->cubic_to( &vec1, &vec2, &v_start, user );
- goto Close;
- }
- }
- }
-
- /* close the contour with a line segment */
- error = interface->line_to( &v_start, user );
-
- Close:
- if ( error )
- goto Exit;
-
- first = last + 1;
- }
-
- return 0;
-
- Exit:
- return error;
-
- Invalid_Outline:
- return ErrRaster_Invalid_Outline;
- }
-
-#endif /* _STANDALONE_ */
-
-
- typedef struct TBand_
- {
- FT_Pos min, max;
-
- } TBand;
-
-
- static
- int grays_convert_glyph( RAS_ARG_ FT_Outline* outline )
- {
- static
- FT_Outline_Funcs interface =
- {
- (FT_Outline_MoveTo_Func)Move_To,
- (FT_Outline_LineTo_Func)Line_To,
- (FT_Outline_ConicTo_Func)Conic_To,
- (FT_Outline_CubicTo_Func)Cubic_To,
- 0,
- 0
- };
-
- TBand bands[40], *band;
- int n, num_bands;
- TPos min, max, max_y;
-
-
- /* Set up state in the raster object */
- compute_cbox( RAS_VAR_ outline );
-
- /* clip to target bitmap, exit if nothing to do */
- if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width ||
- ras.max_ey <= 0 || ras.min_ey >= ras.target.rows )
- return 0;
-
- if ( ras.min_ex < 0 ) ras.min_ex = 0;
- if ( ras.min_ey < 0 ) ras.min_ey = 0;
-
- if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width;
- if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows;
-
- /* simple heuristic used to speed-up the bezier decomposition */
- /* see the code in render_conic and render_cubic for more details */
- ras.conic_level = 32;
- ras.cubic_level = 16;
-
- {
- int level = 0;
-
-
- if ( ras.max_ex > 24 || ras.max_ey > 24 )
- level++;
- if ( ras.max_ex > 120 || ras.max_ey > 120 )
- level += 2;
-
- ras.conic_level <<= level;
- ras.cubic_level <<= level;
- }
-
- /* setup vertical bands */
- num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
- if ( num_bands == 0 ) num_bands = 1;
- if ( num_bands >= 39 ) num_bands = 39;
-
- ras.band_shoot = 0;
-
- min = ras.min_ey;
- max_y = ras.max_ey;
-
- for ( n = 0; n < num_bands; n++, min = max )
- {
- max = min + ras.band_size;
- if ( n == num_bands - 1 || max > max_y )
- max = max_y;
-
- bands[0].min = min;
- bands[0].max = max;
- band = bands;
-
- while ( band >= bands )
- {
- FT_Pos bottom, top, middle;
- int error;
-
-
- ras.num_cells = 0;
- ras.invalid = 1;
- ras.min_ey = band->min;
- ras.max_ey = band->max;
-
- error = FT_Outline_Decompose( outline, &interface, &ras ) ||
- record_cell( RAS_VAR );
-
- if ( !error )
- {
-#ifdef SHELL_SORT
- shell_sort( ras.cells, ras.num_cells );
-#else
- quick_sort( ras.cells, ras.num_cells );
-#endif
-
-#ifdef DEBUG_GRAYS
- check_sort( ras.cells, ras.num_cells );
- dump_cells( RAS_VAR );
-#endif
-
- grays_sweep( RAS_VAR_ &ras.target );
- band--;
- continue;
- }
-
- /* render pool overflow, we will reduce the render band by half */
- bottom = band->min;
- top = band->max;
- middle = bottom + ( ( top - bottom ) >> 1 );
-
- /* waoow! This is too complex for a single scanline, something */
- /* must be really rotten here! */
- if ( middle == bottom )
- {
-#ifdef DEBUG_GRAYS
- fprintf( stderr, "Rotten glyph!\n" );
-#endif
- return 1;
- }
-
- if ( bottom-top >= ras.band_size )
- ras.band_shoot++;
-
- band[1].min = bottom;
- band[1].max = middle;
- band[0].min = middle;
- band[0].max = top;
- band++;
- }
- }
-
- if ( ras.band_shoot > 8 && ras.band_size > 16 )
- ras.band_size = ras.band_size / 2;
-
- return 0;
- }
-
-
- extern
- int grays_raster_render( PRaster raster,
- FT_Raster_Params* params )
- {
- FT_Outline* outline = (FT_Outline*)params->source;
- FT_Bitmap* target_map = params->target;
-
-
- if ( !raster || !raster->cells || !raster->max_cells )
- return -1;
-
- /* return immediately if the outline is empty */
- if ( outline->n_points == 0 || outline->n_contours <= 0 )
- return 0;
-
- if ( !outline || !outline->contours || !outline->points )
- return ErrRaster_Invalid_Outline;
-
- if ( outline->n_points !=
- outline->contours[outline->n_contours - 1] + 1 )
- return ErrRaster_Invalid_Outline;
-
- if ( !target_map || !target_map->buffer )
- return -1;
-
- /* XXXX: this version does not support monochrome rendering yet! */
- if ( !(params->flags & ft_raster_flag_aa) )
- return -1;
-
- ras.outline = *outline;
- ras.target = *target_map;
- ras.num_cells = 0;
- ras.invalid = 1;
-
- ras.render_span = (FT_Raster_Span_Func)grays_render_span;
- ras.render_span_data = &ras;
-
- if ( params->flags & ft_raster_flag_direct )
- {
- ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
- ras.render_span_data = params->user;
- }
-
- return grays_convert_glyph( (PRaster)raster, outline );
- }
-
-
- /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
- /**** a static object. *****/
-
-#ifdef _STANDALONE_
-
- static
- int grays_raster_new( void* memory,
- FT_Raster* araster )
- {
- static TRaster the_raster;
-
- UNUSED( memory );
-
-
- *araster = (FT_Raster)&the_raster;
- memset( &the_raster, 0, sizeof ( the_raster ) );
-
- return 0;
- }
-
-
- static
- void grays_raster_done( FT_Raster raster )
- {
- /* nothing */
- UNUSED( raster );
- }
-
-#else /* _STANDALONE_ */
-
- static
- int grays_raster_new( FT_Memory memory,
- FT_Raster* araster )
- {
- FT_Error error;
- PRaster raster;
-
-
- *araster = 0;
- if ( !ALLOC( raster, sizeof ( TRaster ) ) )
- {
- raster->memory = memory;
- *araster = (FT_Raster)raster;
- }
-
- return error;
- }
-
-
- static
- void grays_raster_done( FT_Raster raster )
- {
- FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;
-
-
- FREE( raster );
- }
-
-#endif /* _STANDALONE_ */
-
-
- static
- void grays_raster_reset( FT_Raster raster,
- const char* pool_base,
- long pool_size )
- {
- PRaster rast = (PRaster)raster;
-
-
- if ( raster && pool_base && pool_size >= 4096 )
- init_cells( rast, (char*)pool_base, pool_size );
-
- rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8;
- }
-
-
- FT_Raster_Funcs ft_grays_raster =
- {
- ft_glyph_format_outline,
-
- (FT_Raster_New_Func) grays_raster_new,
- (FT_Raster_Reset_Func) grays_raster_reset,
- (FT_Raster_Set_Mode_Func)0,
- (FT_Raster_Render_Func) grays_raster_render,
- (FT_Raster_Done_Func) grays_raster_done
- };
-
-
-/* END */
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -20,8 +20,8 @@
/* The purpose of this file is to implement the following two */
/* functions: */
/* */
- /* FT_Default_Drivers(): */
- /* This function is used to add the set of default drivers to a */
+ /* FT_Add_Default_Modules(): */
+ /* This function is used to add the set of default modules to a */
/* fresh new library object. The set is taken from the header file */
/* `freetype/config/ftmodule.h'. See the document `FreeType 2.0 */
/* Build System' for more information. */
@@ -40,7 +40,7 @@
#include <freetype/config/ftconfig.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftdriver.h>
+#include <freetype/ftmodule.h>
/*************************************************************************/
@@ -52,16 +52,16 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_init
-#undef FT_DRIVER
-#define FT_DRIVER( x ) extern FT_DriverInterface x;
+#undef FT_USE_MODULE
+#define FT_USE_MODULE( x ) extern const FT_Module_Class* x;
#include <freetype/config/ftmodule.h>
-#undef FT_DRIVER
-#define FT_DRIVER( x ) &x,
+#undef FT_USE_MODULE
+#define FT_USE_MODULE( x ) (const FT_Module_Class*)&x,
static
-const FT_DriverInterface* ft_default_drivers[] =
+const FT_Module_Class* ft_default_modules[] =
{
#include <freetype/config/ftmodule.h>
0
@@ -71,7 +71,7 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Default_Drivers */
+ /* FT_Add_Default_Modules */
/* */
/* <Description> */
/* Adds the set of default drivers to a given library object. */
@@ -79,23 +79,22 @@
/* <InOut> */
/* library :: A handle to a new library object. */
/* */
- FT_EXPORT_FUNC( void ) FT_Default_Drivers( FT_Library library )
+ FT_EXPORT_FUNC( void ) FT_Add_Default_Modules( FT_Library library )
{
- FT_Error error;
- const FT_DriverInterface** cur;
+ FT_Error error;
+ const FT_Module_Class** cur;
+ /* test for valid library delayed to FT_Add_Module() */
- /* test for valid library delayed to FT_Add_Driver() */
-
- cur = ft_default_drivers;
+ cur = ft_default_modules;
while ( *cur )
{
- error = FT_Add_Driver( library, *cur );
+ error = FT_Add_Module( library, *cur );
/* notify errors, but don't stop */
if ( error )
{
- FT_ERROR(( "FT_Default_Drivers: Cannot install `%s', error = %x\n",
- (*cur)->driver_name, error ));
+ FT_ERROR(( "FT_Add_Default_Module: Cannot install `%s', error = %x\n",
+ (*cur)->module_name, error ));
}
cur++;
}
@@ -115,7 +114,7 @@
/* library :: A handle to a new library object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* FreeTyoe error code. 0 means success. */
/* */
FT_EXPORT_FUNC( FT_Error ) FT_Init_FreeType( FT_Library* library )
{
@@ -139,7 +138,7 @@
error = FT_New_Library( memory, library );
if ( !error )
- FT_Default_Drivers( *library );
+ FT_Add_Default_Modules( *library );
return error;
}
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -47,8 +47,8 @@
FT_Get_MM_Func func;
- func = (FT_Get_MM_Func)driver->interface.get_interface(
- driver, "get_mm" );
+ func = (FT_Get_MM_Func)driver->root.clazz->get_interface(
+ FT_MODULE(driver), "get_mm" );
if ( func )
error = func( face, master );
}
@@ -76,8 +76,8 @@
FT_Set_MM_Design_Func func;
- func = (FT_Set_MM_Design_Func)driver->interface.get_interface(
- driver, "set_mm_design" );
+ func = (FT_Set_MM_Design_Func)driver->root.clazz->get_interface(
+ FT_MODULE(driver), "set_mm_design" );
if ( func )
error = func( face, num_coords, coords );
}
@@ -105,8 +105,8 @@
FT_Set_MM_Blend_Func func;
- func = (FT_Set_MM_Blend_Func)driver->interface.get_interface(
- driver, "set_mm_blend" );
+ func = (FT_Set_MM_Blend_Func)driver->root.clazz->get_interface(
+ FT_MODULE(driver), "set_mm_blend" );
if ( func )
error = func( face, num_coords, coords );
}
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -199,7 +199,19 @@
}
}
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** S T R E A M ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
/*************************************************************************/
/* */
/* <Function> */
@@ -298,12 +310,15 @@
}
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_objs
+
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/**** ****/
/**** ****/
- /**** O B J E C T M A N A G E M E N T ****/
+ /**** G L Y P H L O A D E R ****/
/**** ****/
/**** ****/
/*************************************************************************/
@@ -310,425 +325,421 @@
/*************************************************************************/
/*************************************************************************/
+ /**************************************************************************
+ *
+ * The glyph loader is a simple object which is used to load a set of
+ * glyphs easily. It is critical for the correct loading of composites.
+ *
+ * Ideally, one can see it as a stack of abstract "glyph" objects.
+ *
+ * loader.base is really the bottom of the stack. It describes a
+ * single glyph image made of the juxtaposition of several
+ * glyphs (those 'in the stack')
+ *
+ * loader.current describes the top of the stack, on which a new
+ * glyph can be loaded.
+ *
+ * Rewind clears the stack
+ * Prepare means set up "loader.current" for addition of a new glyph image
+ * Add means add the 'current' glyph image to the 'base' one, and
+ * prepare for another one..
+ *
+ * the glyph loader is now a base object. Each driver used to re-implement
+ * it in one way or the other, which wasted code and energy..
+ *
+ *************************************************************************/
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_objs
-
-
- /* destructor for sizes list */
- static
- void destroy_size( FT_Memory memory,
- FT_Size size,
- FT_Driver driver )
+ /* create a new glyph loader */
+ BASE_FUNC(FT_Error) FT_GlyphLoader_New( FT_Memory memory,
+ FT_GlyphLoader* *aloader )
{
- /* finalize format-specific stuff */
- driver->interface.done_size( size );
- FREE( size );
+ FT_GlyphLoader* loader;
+ FT_Error error;
+
+ if (!ALLOC(loader, sizeof(*loader)))
+ {
+ loader->memory = memory;
+ *aloader = loader;
+ }
+ return error;
}
- /* destructor for faces list */
- static
- void destroy_face( FT_Memory memory,
- FT_Face face,
- FT_Driver driver )
+ /* rewind the glyph loader - reset counters to 0 */
+ BASE_FUNC(void) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
{
- /* Discard glyph slots for this face */
- /* XXX: Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
- while ( face->glyph )
- FT_Done_GlyphSlot( face->glyph );
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
- /* Discard all sizes for this face */
- FT_List_Finalize( &face->sizes_list,
- (FT_List_Destructor)destroy_size,
- memory,
- driver );
- face->size = 0;
+ base->outline.n_points = 0;
+ base->outline.n_contours = 0;
+ base->num_subglyphs = 0;
- /* finalize format-specific stuff */
- driver->interface.done_face( face );
+ *current = *base;
+ }
- /* Now discard client data */
- if ( face->generic.finalizer )
- face->generic.finalizer( face );
- /* close the stream for this face */
- ft_done_stream( &face->stream );
+ /* reset the glyph loader, frees all allocated tables and starts from zero */
+ BASE_FUNC(void) FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
+ {
+ FT_Memory memory = loader->memory;
- /* get rid of it */
- FREE( face );
+ FREE( loader->base.outline.points );
+ FREE( loader->base.outline.tags );
+ FREE( loader->base.outline.contours );
+ FREE( loader->base.extra_points );
+ FREE( loader->base.subglyphs );
+
+ loader->max_points = 0;
+ loader->max_contours = 0;
+ loader->max_subglyphs = 0;
+
+ FT_GlyphLoader_Rewind( loader );
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Destroy_Driver */
- /* */
- /* <Description> */
- /* Destroys a given driver object. This also destroys all child */
- /* faces. */
- /* */
- /* <InOut> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Note> */
- /* The driver _must_ be LOCKED! */
- /* */
- static
- void Destroy_Driver( FT_Driver driver )
+ /* delete a glyph loader */
+ BASE_FUNC(void) FT_GlyphLoader_Done( FT_GlyphLoader* loader )
{
- FT_Memory memory = driver->memory;
+ if (loader)
+ {
+ FT_Memory memory = loader->memory;
+ FT_GlyphLoader_Reset(loader);
+ FREE( loader );
+ }
+ }
- /* now, finalize all faces in the driver list */
- FT_List_Finalize( &driver->faces_list,
- (FT_List_Destructor)destroy_face,
- memory,
- driver );
- /* finalize the driver object */
- if ( driver->interface.done_driver )
- driver->interface.done_driver( driver );
+ /* re-adjust the 'current' outline fields */
+ static void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
+ {
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
- /* finalize client-data */
- if ( driver->generic.finalizer )
- driver->generic.finalizer( driver );
-
- /* discard it */
- FREE( driver );
+ current->points = base->points + base->n_points;
+ current->tags = base->tags + base->n_points;
+ current->contours = base->contours + base->n_contours;
+
+ /* handle extra points table - if any */
+ if (loader->use_extra)
+ loader->current.extra_points = loader->base.extra_points + base->n_points;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Get_Raster */
- /* */
- /* <Description> */
- /* Returns the raster interface corresponding to a given glyph format */
- /* tag. */
- /* */
- /* <Input> */
- /* library :: A handle to the source library object. */
- /* */
- /* glyph_format :: The glyph format tag. */
- /* */
- /* <Output> */
- /* raster_funcs :: If this field is not 0, the raster's interface */
- /* functions are returned. */
- /* */
- /* <Return> */
- /* A pointer to the corresponding raster object. */
- /* */
- FT_EXPORT_FUNC( FT_Raster ) FT_Get_Raster(
- FT_Library library,
- FT_Glyph_Format glyph_format,
- FT_Raster_Funcs* raster_funcs )
+
+ BASE_FUNC(FT_Error) FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader )
{
- FT_Int n;
+ FT_Error error;
+ FT_Memory memory = loader->memory;
+
+ if ( !ALLOC_ARRAY( loader->base.extra_points,
+ loader->max_points, FT_Vector ) )
+ {
+ loader->use_extra = 1;
+ FT_GlyphLoader_Adjust_Points(loader);
+ }
+ return error;
+ }
- if ( !library )
- return 0;
- for ( n = 0; n < FT_MAX_GLYPH_FORMATS; n++ )
- {
- FT_Raster_Funcs* funcs = &library->raster_funcs[n];
+ /* re-adjust the 'current' subglyphs field */
+ static void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
- if ( funcs->glyph_format == glyph_format )
- {
- if ( raster_funcs )
- *raster_funcs = *funcs;
- return library->rasters[n];
- }
- }
- return 0;
+ current->subglyphs = base->subglyphs + base->num_subglyphs;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Raster */
- /* */
- /* <Description> */
- /* Registers a given raster to the library. */
- /* */
- /* <Input> */
- /* library :: A handle to a target library object. */
- /* */
- /* raster_funcs :: A pointer to the raster's interface functions. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function will do the following: */
- /* */
- /* - A new raster object is created through `raster_func.raster_new'. */
- /* If this fails, the function returns. */
- /* */
- /* - If a raster is already registered for the glyph format */
- /* specified in raster_funcs, it will be destroyed. */
- /* */
- /* - The new raster is registered for the glyph format. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_Set_Raster( FT_Library library,
- FT_Raster_Funcs* raster_funcs )
+ /* ensure that we can add n_points and n_contours to our glyph. this */
+ /* function reallocates its outline tables if necessary. Note that */
+ /* it DOESN'T change the number of points within the loader !! */
+ BASE_FUNC(FT_Error) FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
+ FT_UInt n_points,
+ FT_UInt n_contours )
{
- FT_Glyph_Format glyph_format;
- FT_Raster_Funcs* funcs;
- FT_Raster raster;
- FT_Error error;
- FT_Int n, index;
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_Outline* base = &loader->base.outline;
+ FT_Outline* current = &loader->current.outline;
+ FT_Bool adjust = 1;
+ FT_UInt new_max;
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
+ /* check points & tags */
+ new_max = base->n_points + current->n_points + n_points;
+ if (new_max > loader->max_points)
+ {
+ new_max = (new_max+7) & -8;
+ if ( REALLOC_ARRAY( base->points, base->n_points, new_max, FT_Vector ) ||
+ REALLOC_ARRAY( base->tags, base->n_points, new_max, FT_Byte ) )
+ goto Exit;
- if ( !raster_funcs )
- return FT_Err_Invalid_Argument;
+ if ( loader->use_extra &&
+ REALLOC_ARRAY( loader->base.extra_points, base->n_points, new_max,
+ FT_Vector ) )
+ goto Exit;
- glyph_format = raster_funcs->glyph_format;
+ adjust = 1;
+ loader->max_points = new_max;
+ }
- if ( glyph_format == ft_glyph_format_none )
- return FT_Err_Invalid_Argument;
+ /* check contours */
+ new_max = base->n_contours + current->n_contours +
+ n_contours;
+ if (new_max > loader->max_contours)
+ {
+ new_max = (new_max+3) & -4;
+ if (REALLOC_ARRAY( base->contours, base->n_contours, new_max, FT_Short ))
+ goto Exit;
- /* create a new raster object */
- error = raster_funcs->raster_new( library->memory, &raster );
- if ( error )
- goto Exit;
+ adjust = 1;
+ loader->max_contours = new_max;
+ }
- raster_funcs->raster_reset( raster,
- library->raster_pool,
- library->raster_pool_size );
+ if (adjust)
+ FT_GlyphLoader_Adjust_Points( loader );
- index = -1;
- for ( n = 0; n < FT_MAX_GLYPH_FORMATS; n++ )
- {
- FT_Raster_Funcs* funcs = library->raster_funcs + n;
+ Exit:
+ return error;
+ }
- /* record the first vacant entry in `index' */
- if ( index < 0 && funcs->glyph_format == ft_glyph_format_none )
- index = n;
+ /* ensure that we can add n_subglyphs to our glyph. this function */
+ /* reallocates its subglyphs table if necessary. Note that it DOES */
+ /* NOT change the number of subglyphs within the loader !! */
+ BASE_FUNC(FT_Error) FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
+ FT_UInt n_subs )
+ {
+ FT_Memory memory = loader->memory;
+ FT_Error error = FT_Err_Ok;
+ FT_UInt new_max;
- /* compare this entry's glyph format with the one we need */
- if ( funcs->glyph_format == glyph_format )
- {
- /* A raster already exists for this glyph format. We will */
- /* destroy it before updating its entry in the table. */
- funcs->raster_done( library->rasters[n] );
- index = n;
- break;
- }
- }
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
- if ( index < 0 )
+ new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
+ if (new_max > loader->max_subglyphs)
{
- /* the table is full and has no vacant entries */
- error = FT_Err_Too_Many_Glyph_Formats;
- goto Fail;
- }
+ new_max = (new_max+1) & -2;
+ if (REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
+ new_max, FT_SubGlyph ))
+ goto Exit;
- funcs = library->raster_funcs + index;
- *funcs = *raster_funcs;
- library->rasters[index] = raster;
+ loader->max_subglyphs = new_max;
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
+
Exit:
return error;
-
- Fail:
- raster_funcs->raster_done( raster );
- goto Exit;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Unset_Raster */
- /* */
- /* <Description> */
- /* Removes a given raster from the library. */
- /* */
- /* <Input> */
- /* library :: A handle to a target library object. */
- /* */
- /* raster_funcs :: A pointer to the raster's interface functions. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_DEF( FT_Error ) FT_Unset_Raster(
- FT_Library library,
- FT_Raster_Funcs* raster_funcs )
+ /* prepare loader for the addition of a new glyph on top of the base one */
+ BASE_FUNC(void) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
{
- FT_Glyph_Format glyph_format;
- FT_Error error;
- FT_Int n;
+ FT_GlyphLoad* current = &loader->current;
+ current->outline.n_points = 0;
+ current->outline.n_contours = 0;
+ current->num_subglyphs = 0;
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
+ FT_GlyphLoader_Adjust_Points ( loader );
+ FT_GlyphLoader_Adjust_Subglyphs( loader );
+ }
- error = FT_Err_Invalid_Argument;
- if ( !raster_funcs )
- goto Exit;
+ /* add current glyph to the base image - and prepare for another */
+ BASE_FUNC(void) FT_GlyphLoader_Add( FT_GlyphLoader* loader )
+ {
+ FT_GlyphLoad* base = &loader->base;
+ FT_GlyphLoad* current = &loader->current;
- glyph_format = raster_funcs->glyph_format;
+ FT_UInt n_curr_contours = current->outline.n_contours;
+ FT_UInt n_base_points = base->outline.n_points;
+ FT_UInt n;
- if ( glyph_format == ft_glyph_format_none )
- goto Exit;
+ base->outline.n_points += current->outline.n_points;
+ base->outline.n_contours += current->outline.n_contours;
+ base->num_subglyphs += current->num_subglyphs;
- for ( n = 0; n < FT_MAX_GLYPH_FORMATS; n++ )
- {
- FT_Raster_Funcs* funcs = library->raster_funcs + n;
+ /* adjust contours count in newest outline */
+ for ( n = 0; n < n_curr_contours; n++ )
+ current->outline.contours[n] += n_base_points;
+ /* prepare for another new glyph image */
+ FT_GlyphLoader_Prepare( loader );
+ }
- if ( funcs->glyph_format == glyph_format )
- {
- funcs->raster_done( library->rasters[n] );
- library->rasters[n] = 0;
- library->raster_funcs[n].glyph_format = ft_glyph_format_none;
- error = FT_Err_Ok;
- break;
- }
+
+ BASE_FUNC(FT_Error) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
+ FT_GlyphLoader* source )
+ {
+ FT_Error error;
+ FT_UInt num_points = source->base.outline.n_points;
+ FT_UInt num_contours = source->base.outline.n_contours;
+
+ error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
+ if (!error)
+ {
+ FT_Outline* out = &target->base.outline;
+ FT_Outline* in = &source->base.outline;
+
+ MEM_Copy( out->points, in->points, num_points * sizeof(FT_Vector) );
+ MEM_Copy( out->tags, in->tags, num_points * sizeof(char) );
+ MEM_Copy( out->contours, in->contours, num_contours * sizeof(short) );
+
+ /* do we need to copy the extra points ? */
+ if (target->use_extra && source->use_extra)
+ MEM_Copy( target->base.extra_points, source->base.extra_points,
+ num_points * sizeof(FT_Vector) );
+
+ out->n_points = num_points;
+ out->n_contours = num_contours;
+
+ FT_GlyphLoader_Adjust_Points( target );
}
+ return error;
+ }
- Exit:
- return error;
- }
/*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Raster_Mode */
- /* */
- /* <Description> */
- /* Sets a raster-specific mode. */
- /* */
- /* <InOut> */
- /* library :: A handle to a target library object. */
- /* */
- /* <Input> */
- /* format :: The glyph format used to select the raster. */
- /* */
- /* mode :: The raster-specific mode descriptor. */
- /* */
- /* args :: The mode arguments. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_Set_Raster_Mode( FT_Library library,
- FT_Glyph_Format format,
- unsigned long mode,
- void* args )
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static FT_Error ft_glyphslot_init( FT_GlyphSlot slot )
{
- FT_Raster_Funcs funcs;
- FT_Raster raster;
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class* clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+ FT_Error error = FT_Err_Ok;
+ if (FT_DRIVER_USES_OUTLINES(driver))
+ error = FT_GlyphLoader_New( memory, &slot->loader );
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
+ if (!error && clazz->init_slot)
+ error = clazz->init_slot( slot );
- raster = FT_Get_Raster( library, format, &funcs );
- if ( raster && args && funcs.raster_set_mode )
- return funcs.raster_set_mode( raster, mode, args );
- else
- return FT_Err_Invalid_Argument;
+ return error;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Set_Debug_Hook */
- /* */
- /* <Description> */
- /* Sets a debug hook function for debugging the interpreter of a */
- /* font format. */
- /* */
- /* <Input> */
- /* library :: A handle to the library object. */
- /* */
- /* hook_index :: The index of the debug hook. You should use the */
- /* values defined in ftobjs.h, e.g. */
- /* FT_DEBUG_HOOK_TRUETYPE */
- /* */
- /* debug_hook :: The function used to debug the interpreter. */
- /* */
- /* <Note> */
- /* Currently, four debug hook slots are available, but only two (for */
- /* the TrueType and the Type 1 interpreter) are defined. */
- /* */
- FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
- FT_UInt hook_index,
- FT_DebugHook_Func debug_hook )
+ static void ft_glyphslot_clear( FT_GlyphSlot slot )
{
- if ( library && debug_hook &&
- hook_index <
- ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
- library->debug_hooks[hook_index] = debug_hook;
+ /* clear all public fields in the glyph slot */
+ MEM_Set( &slot->metrics, 0, sizeof(slot->metrics) );
+ MEM_Set( &slot->outline, 0, sizeof(slot->outline) );
+ MEM_Set( &slot->bitmap, 0, sizeof(slot->bitmap) );
+
+ slot->bitmap_left = 0;
+ slot->bitmap_top = 0;
+ slot->num_subglyphs = 0;
+ slot->subglyphs = 0;
+ slot->control_data = 0;
+ slot->control_len = 0;
+ slot->other = 0;
+ slot->format = 0;
+
+ slot->linearHoriAdvance = 0;
+ slot->linearVertAdvance = 0;
}
+ static void ft_glyphslot_done( FT_GlyphSlot slot )
+ {
+ FT_Driver driver = slot->face->driver;
+ FT_Driver_Class* clazz = driver->clazz;
+ FT_Memory memory = driver->root.memory;
+
+ /* free bitmap buffer if needed */
+ if ( slot->flags & ft_glyph_own_bitmap )
+ FREE( slot->bitmap.buffer );
+
+ /* free glyph loader */
+ if (FT_DRIVER_USES_OUTLINES(driver))
+ {
+ FT_GlyphLoader_Done( slot->loader );
+ slot->loader = 0;
+ }
+
+ if (clazz->done_slot)
+ clazz->done_slot( slot );
+ }
+
+
+
+
/*************************************************************************/
/* */
/* <Function> */
- /* FT_New_Library */
+ /* FT_New_GlyphSlot */
/* */
/* <Description> */
- /* This function is used to create a new FreeType library instance */
- /* from a given memory object. It is thus possible to use libraries */
- /* with distinct memory allocators within the same program. */
+ /* It is sometimes useful to have more than one glyph slot for a */
+ /* given face object. This function is used to create additional */
+ /* slots. All of them are automatically discarded when the face is */
+ /* destroyed. */
/* */
/* <Input> */
- /* memory :: A handle to the original memory object. */
+ /* face :: A handle to a parent face object. */
/* */
/* <Output> */
- /* alibrary :: A pointer to handle of a new library object. */
+ /* aslot :: A handle to a new glyph slot object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
- FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
- FT_Library* alibrary )
+
+ FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
+ FT_GlyphSlot* aslot )
{
- FT_Library library = 0;
- FT_Error error;
+ FT_Error error;
+ FT_Driver driver;
+ FT_Driver_Class* clazz;
+ FT_Memory memory;
+ FT_GlyphSlot slot;
+ *aslot = 0;
- if ( !memory )
+ if ( !face || !aslot || !face->driver )
return FT_Err_Invalid_Argument;
- /* first of all, allocate the library object */
- if ( ALLOC( library, sizeof ( *library ) ) )
- return error;
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
- library->memory = memory;
+ FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
+ if ( !ALLOC( slot, clazz->slot_object_size ) )
+ {
+ slot->face = face;
- /* allocate the render pool */
- library->raster_pool_size = FT_RENDER_POOL_SIZE;
- if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
- goto Fail;
+ error = ft_glyphslot_init( slot );
+ if (error)
+ {
+ ft_glyphslot_done( slot );
+ FREE( slot );
+ goto Exit;
+ }
- /* now register the default raster for the `outline' glyph image */
- /* format for now, ignore the error... */
- error = FT_Set_Raster( library, &ft_default_raster );
+ *aslot = slot;
+ }
- /* That's ok now */
- *alibrary = library;
-
- return FT_Err_Ok;
-
- Fail:
- FREE( library );
+ Exit:
+ FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
return error;
}
@@ -736,140 +747,108 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Done_Library */
+ /* FT_Done_GlyphSlot */
/* */
/* <Description> */
- /* Discards a given library object. This closes all drivers and */
- /* discards all resource objects. */
+ /* Destroys a given glyph slot. Remember however that all slots are */
+ /* automatically destroyed with its parent. Using this function is */
+ /* not always mandatory. */
/* */
/* <Input> */
- /* library :: A handle to the target library. */
+ /* slot :: A handle to a target glyph slot. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
+ FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
{
- FT_Memory memory;
- FT_Int n;
-
-
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
-
- memory = library->memory;
-
- /* Discard client-data */
- if ( library->generic.finalizer )
- library->generic.finalizer( library );
-
- /* Close all drivers in the library */
- for ( n = 0; n < library->num_drivers; n++ )
+ if ( slot )
{
- FT_Driver driver = library->drivers[n];
+ FT_Driver driver = slot->face->driver;
+ FT_Memory memory = driver->root.memory;
+ FT_GlyphSlot* parent;
+ FT_GlyphSlot cur;
-
- if ( driver )
+ /* Remove slot from its parent face's list */
+ parent = &slot->face->glyph;
+ cur = *parent;
+ while ( cur )
{
- Destroy_Driver( driver );
- library->drivers[n] = 0;
- }
- }
-
- /* Destroy raster objects */
- FREE( library->raster_pool );
- library->raster_pool_size = 0;
-
- {
- FT_Raster_Funcs* cur = library->raster_funcs;
- FT_Raster_Funcs* limit = cur + FT_MAX_GLYPH_FORMATS;
- FT_Raster* raster = library->rasters;
-
- for ( ; cur < limit; cur++, raster++ )
- {
- if ( cur->glyph_format != ft_glyph_format_none )
+ if ( cur == slot )
{
- cur->raster_done( *raster );
- *raster = 0;
- cur->glyph_format = ft_glyph_format_none;
+ *parent = cur->next;
+ ft_glyphslot_done(slot);
+ FREE( slot );
+ break;
}
+ cur = cur->next;
}
}
+ }
- FREE( library );
- return FT_Err_Ok;
- }
+ /* forward declaration */
+ static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
+
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Add_Driver */
+ /* FT_Set_Transform */
/* */
/* <Description> */
- /* Registers a new driver in a given library object. This function */
- /* takes only a pointer to a driver interface; it uses it to create */
- /* the new driver, then sets up some important fields. */
+ /* A function used to set the transformation that is applied to glyph */
+ /* images just before they're converted to bitmaps in a glyph slot */
+ /* when FT_Render_Glyph is called.. */
/* */
/* <InOut> */
- /* library :: A handle to the target library object. */
+ /* face :: A handle to the source face object. */
/* */
/* <Input> */
- /* driver_interface :: A pointer to a driver interface table. */
+ /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
+ /* the identity matrix. */
+ /* delta :: A pointer to the translation vector. Use 0 for the null */
+ /* vector. */
/* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
/* <Note> */
- /* This function doesn't check whether the driver is already */
- /* installed! */
+ /* The transformation is only applied to scalable image formats. */
/* */
- FT_EXPORT_FUNC( FT_Error ) FT_Add_Driver(
- FT_Library library,
- const FT_DriverInterface* driver_interface )
+ FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
{
- FT_Error error;
- FT_Driver driver;
- FT_Memory memory;
+ if ( !face )
+ return;
+ face->transform_flags = 0;
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
-
- if ( !driver_interface )
- return FT_Err_Invalid_Argument;
-
- memory = library->memory;
- error = FT_Err_Ok;
-
- if ( library->num_drivers >= FT_MAX_DRIVERS )
- error = FT_Err_Too_Many_Drivers;
- else
+ if ( !matrix )
{
- if ( ALLOC( driver, driver_interface->driver_object_size ) )
- goto Exit;
+ face->transform_matrix.xx = 0x10000L;
+ face->transform_matrix.xy = 0L;
+ face->transform_matrix.yx = 0L;
+ face->transform_matrix.yy = 0x10000L;
+ matrix = &face->transform_matrix;
+ }
+ else
+ face->transform_matrix = *matrix;
- driver->library = library;
- driver->memory = memory;
- driver->interface = *driver_interface;
+ /* set transform_flags bit flag 0 if `matrix' isn't the identity */
+ if ( ( matrix->xy | matrix->yx ) ||
+ matrix->xx != 0x10000L ||
+ matrix->yy != 0x10000L )
+ face->transform_flags |= 1;
- if ( driver_interface->init_driver )
- {
- error = driver_interface->init_driver( driver );
- if ( error )
- goto Fail;
- }
-
- library->drivers[library->num_drivers++] = driver;
- goto Exit;
-
- Fail:
- FREE( driver );
+ if ( !delta )
+ {
+ face->transform_delta.x = 0;
+ face->transform_delta.y = 0;
+ delta = &face->transform_delta;
}
+ else
+ face->transform_delta = *delta;
- Exit:
- return error;
+ /* set transform_flags bit flag 1 if `delta' isn't the null vector */
+ if ( delta->x | delta->y )
+ face->transform_flags |= 2;
}
@@ -876,63 +855,93 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Remove_Driver */
+ /* FT_Load_Glyph */
/* */
/* <Description> */
- /* Unregisters a given driver. This closes the driver, which in turn */
- /* destroys all faces, sizes, slots, etc. associated with it. */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size. */
/* */
- /* This function also DESTROYS the driver object. */
- /* */
/* <Input> */
- /* driver :: A handle to target driver object. */
+ /* face :: A handle to the target face object where the glyph */
+ /* will be 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). */
+ /* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
- FT_EXPORT_FUNC( FT_Error ) FT_Remove_Driver( FT_Driver driver )
+ /* <Note> */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the "face.glyph.advance" field, */
+ /* but **NOT** the values in "face.glyph.metrics".. */
+ /* */
+
+ FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
+ FT_UInt glyph_index,
+ FT_Int load_flags )
{
- FT_Library library;
- FT_Memory memory;
- FT_Driver *cur, *last;
- FT_Error error;
+ FT_Error error;
+ FT_Driver driver;
+ FT_GlyphSlot slot;
+ if ( !face || !face->size || !face->glyph )
+ return FT_Err_Invalid_Face_Handle;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
+ if ( glyph_index >= face->num_glyphs )
+ return FT_Err_Invalid_Argument;
- library = driver->library;
- memory = driver->memory;
+ slot = face->glyph;
+ ft_glyphslot_clear( slot );
- if ( !library || !memory )
- return FT_Err_Invalid_Driver_Handle;
+ driver = face->driver;
- /* look-up driver entry in library table */
- error = FT_Err_Invalid_Driver_Handle;
- cur = library->drivers;
- last = cur + library->num_drivers - 1;
+ /* when the flag NO_RECURSE is set, we disable hinting and scaling */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
- for ( ; cur <= last; cur++ )
+ error = driver->clazz->load_glyph( slot,
+ face->size,
+ glyph_index,
+ load_flags );
+ if (error) goto Exit;
+
+ /* compute the advance */
+ if (load_flags & FT_LOAD_VERTICAL_LAYOUT)
{
- if ( *cur == driver )
- {
- /* destroy the driver object */
- Destroy_Driver( driver );
+ slot->advance.x = 0;
+ slot->advance.y = slot->metrics.vertAdvance;
+ }
+ else
+ {
+ slot->advance.x = slot->metrics.horiAdvance;
+ slot->advance.y = 0;
+ }
- /* now move the last driver in the table to the vacant slot */
- if ( cur < last )
- {
- *cur = *last;
- *last = 0;
- }
- library->num_drivers--;
-
- /* exit loop */
- error = FT_Err_Ok;
- break;
- }
+ /* now, transform the glyph image when needed */
+ if (face->transform_flags)
+ {
+ /* get renderer */
+ FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
+
+ if (renderer)
+ error = renderer->clazz->transform_glyph( renderer, slot,
+ &face->transform_matrix,
+ &face->transform_delta );
+ /* transform advance */
+ FT_Vector_Transform( &slot->advance, &face->transform_matrix );
}
+ Exit:
return error;
}
@@ -940,39 +949,131 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Get_Driver */
+ /* FT_Load_Char */
/* */
/* <Description> */
- /* Returns the handle of the driver responsible for a given format */
- /* (or service) according to its `name'. */
+ /* A function used to load a single glyph within a given glyph slot, */
+ /* for a given size, according to its character code ! */
/* */
/* <Input> */
- /* library :: A handle to the library object. */
- /* driver_name :: The name of the driver to look up. */
+ /* face :: A handle to a target face object where the glyph */
+ /* will be loaded. */
/* */
+ /* char_code :: The glyph's character code, according to the */
+ /* current charmap used in the face. */
+ /* */
+ /* 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). */
/* <Return> */
- /* A handle to the driver object, 0 otherwise. */
+ /* FreeType error code. 0 means success. */
/* */
- FT_EXPORT_FUNC( FT_Driver ) FT_Get_Driver( FT_Library library,
- char* driver_name )
+ /* <Note> */
+ /* If the face has no current charmap, or if the character code */
+ /* is not defined in the charmap, this function will return an */
+ /* error.. */
+ /* */
+ /* If the glyph image is not a bitmap, and if the bit flag */
+ /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
+ /* transformed with the information passed to a previous call to */
+ /* FT_Set_Transform. */
+ /* */
+ /* Note that this also transforms the "face.glyph.advance" field, */
+ /* but **NOT** the values in "face.glyph.metrics".. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
+ FT_ULong char_code,
+ FT_Int load_flags )
{
- FT_Driver *cur, *limit;
+ FT_UInt glyph_index;
+ if ( !face )
+ return FT_Err_Invalid_Face_Handle;
- if ( !library || !driver_name )
- return 0;
+ glyph_index = (FT_UInt)char_code;
+ if (face->charmap)
+ glyph_index = FT_Get_Char_Index( face, char_code );
- cur = library->drivers;
- limit = cur + library->num_drivers;
- for ( ; cur < limit; cur++ )
- {
- if ( strcmp( (*cur)->interface.driver_name, driver_name ) == 0 )
- return *cur;
- }
- return 0;
+ return glyph_index ? FT_Load_Glyph( face, glyph_index, load_flags )
+ : FT_Err_Invalid_Character_Code;
}
+
+
+ /* destructor for sizes list */
+ static
+ void destroy_size( FT_Memory memory,
+ FT_Size size,
+ FT_Driver driver )
+ {
+ /* finalize client-specific data */
+ if (size->generic.finalizer)
+ size->generic.finalizer( size );
+
+ /* finalize format-specific stuff */
+ if (driver->clazz->done_size)
+ driver->clazz->done_size( size );
+
+ FREE( size );
+ }
+
+
+ /* destructor for faces list */
+ static
+ void destroy_face( FT_Memory memory,
+ FT_Face face,
+ FT_Driver driver )
+ {
+ FT_Driver_Class* clazz = driver->clazz;
+
+ /* Discard glyph slots for this face */
+ /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
+ while ( face->glyph )
+ FT_Done_GlyphSlot( face->glyph );
+
+ /* Discard all sizes for this face */
+ FT_List_Finalize( &face->sizes_list,
+ (FT_List_Destructor)destroy_size,
+ memory,
+ driver );
+ face->size = 0;
+
+ /* Now discard client data */
+ if ( face->generic.finalizer )
+ face->generic.finalizer( face );
+
+ /* finalize format-specific stuff */
+ if (clazz->done_face)
+ clazz->done_face(face);
+
+ /* close the stream for this face if needed */
+ if ( (face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM) == 0 )
+ ft_done_stream( &face->stream );
+
+ /* get rid of it */
+ FREE( face );
+ }
+
+
+ static void Destroy_Driver( FT_Driver driver )
+ {
+ FT_List_Finalize( &driver->faces_list,
+ (FT_List_Destructor)destroy_face,
+ driver->root.memory,
+ driver );
+
+ /* see if we need to drop the driver's glyph loader */
+ if (FT_DRIVER_USES_OUTLINES(driver))
+ FT_GlyphLoader_Done( driver->glyph_loader );
+
+
+ }
+
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -989,17 +1090,16 @@
FT_Parameter* params,
FT_Face* aface )
{
- FT_Memory memory;
- FT_DriverInterface* interface;
- FT_Face face = 0;
- FT_Error error;
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Face face = 0;
+ FT_Error error;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
- interface = &driver->interface;
- memory = driver->memory;
-
/* allocate the face object, and perform basic initialization */
- if ( ALLOC( face, interface->face_object_size ) )
+ if ( ALLOC( face, clazz->face_object_size ) )
goto Fail;
face->driver = driver;
@@ -1006,11 +1106,11 @@
face->memory = memory;
face->stream = stream;
- error = interface->init_face( stream,
- face,
- face_index,
- num_params,
- params );
+ error = clazz->init_face( stream,
+ face,
+ face_index,
+ num_params,
+ params );
if ( error )
goto Fail;
@@ -1019,7 +1119,7 @@
Fail:
if ( error )
{
- interface->done_face( face );
+ clazz->done_face( face );
FREE( face );
*aface = 0;
}
@@ -1073,9 +1173,7 @@
{
FT_Open_Args args;
-
/* test for valid `library' and `aface' delayed to FT_Open_Face() */
-
if ( !pathname )
return FT_Err_Invalid_Argument;
@@ -1134,9 +1232,7 @@
{
FT_Open_Args args;
-
/* test for valid `library' and `face' delayed to FT_Open_Face() */
-
if ( !file_base )
return FT_Err_Invalid_Argument;
@@ -1211,8 +1307,7 @@
/* create input stream */
error = ft_new_input_stream( library, args, &stream );
- if ( error )
- goto Exit;
+ if ( error ) goto Exit;
memory = library->memory;
@@ -1220,14 +1315,14 @@
/* it. Otherwise, we'll scan the list of registered drivers. */
if ( args->flags & ft_open_driver && args->driver )
{
- driver = args->driver;
- /* not all drivers directly support face objects, so check... */
- if ( driver->interface.face_object_size )
+ driver = FT_DRIVER(args->driver);
+
+ /* not all modules are drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER(driver) )
{
FT_Int num_params = 0;
FT_Parameter* params = 0;
-
if ( args->flags & ft_open_params )
{
num_params = args->num_params;
@@ -1247,18 +1342,18 @@
else
{
/* check each font driver for an appropriate format */
- FT_Driver* cur = library->drivers;
- FT_Driver* limit = cur + library->num_drivers;
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
for ( ; cur < limit; cur++ )
{
- driver = *cur;
- /* not all drivers directly support face objects, so check... */
- if ( driver->interface.face_object_size )
+ /* not all modules are font drivers, so check... */
+ if ( FT_MODULE_IS_DRIVER(cur[0]) )
{
FT_Int num_params = 0;
FT_Parameter* params = 0;
+ driver = FT_DRIVER(cur[0]);
if ( args->flags & ft_open_params )
{
@@ -1284,6 +1379,10 @@
Success:
FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
+ /* set the EXTERNAL_STREAM bit for FT_Done_Face */
+ if ( args->flags & ft_open_stream && args->stream )
+ face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
+
/* add the face object to its driver's list */
if ( ALLOC( node, sizeof ( *node ) ) )
goto Fail;
@@ -1300,8 +1399,9 @@
FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
error = FT_New_GlyphSlot( face, &slot );
- if ( error )
- goto Fail;
+ if ( error ) goto Fail;
+
+ face->glyph = slot;
}
/* finally, allocate a size object for the face */
@@ -1311,8 +1411,9 @@
FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
error = FT_New_Size( face, &size );
- if ( error )
- goto Fail;
+ if ( error ) goto Fail;
+
+ face->size = size;
}
/* initialize transformation for convenience functions */
@@ -1419,9 +1520,8 @@
FT_Error error;
FT_Driver driver;
- FTDriver_getInterface get_interface;
+ FT_Driver_Class* clazz;
-
/* test for valid `parameters' delayed to ft_new_input_stream() */
if ( !face )
@@ -1431,7 +1531,7 @@
if ( !driver )
return FT_Err_Invalid_Driver_Handle;
- error = ft_new_input_stream( driver->library, parameters, &stream );
+ error = ft_new_input_stream( driver->root.library, parameters, &stream );
if ( error )
goto Exit;
@@ -1439,20 +1539,13 @@
/* `attach_file' interface */
error = FT_Err_Unimplemented_Feature;
+ clazz = driver->clazz;
+ if (clazz->attach_file)
+ error = clazz->attach_file( face, stream );
- get_interface = driver->interface.get_interface;
- if ( get_interface )
- {
- FT_Attach_Reader reader;
-
-
- reader = (FT_Attach_Reader)(get_interface( driver, "attach_file" ));
- if ( reader )
- error = reader( face, stream );
- }
-
/* close the attached stream */
- ft_done_stream( &stream );
+ if ( !parameters->stream || (parameters->flags & ft_open_stream) )
+ ft_done_stream( &stream );
Exit:
return error;
@@ -1476,38 +1569,30 @@
/* */
FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face )
{
- FT_Error error;
- FT_Driver driver;
- FT_Memory memory;
- FT_DriverInterface* interface;
- FT_ListNode node;
+ FT_Error error;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_ListNode node;
-
- if ( !face )
- return FT_Err_Invalid_Face_Handle;
-
- driver = face->driver;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
-
- interface = &driver->interface;
- memory = driver->memory;
-
- /* find face in driver's list */
- node = FT_List_Find( &driver->faces_list, face );
- if ( node )
+ error = FT_Err_Invalid_Face_Handle;
+ if ( face && face->driver )
{
- /* remove face object from the driver's list */
- FT_List_Remove( &driver->faces_list, node );
- FREE( node );
-
- /* now destroy the object proper */
- destroy_face( memory, face, driver );
- error = FT_Err_Ok;
+ driver = face->driver;
+ memory = driver->root.memory;
+
+ /* find face in driver's list */
+ node = FT_List_Find( &driver->faces_list, face );
+ if ( node )
+ {
+ /* remove face object from the driver's list */
+ FT_List_Remove( &driver->faces_list, node );
+ FREE( node );
+
+ /* now destroy the object proper */
+ destroy_face( memory, face, driver );
+ error = FT_Err_Ok;
+ }
}
- else
- error = FT_Err_Invalid_Face_Handle;
-
return error;
}
@@ -1532,38 +1617,32 @@
FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face,
FT_Size* asize )
{
- FT_Error error;
- FT_Memory memory;
- FT_Driver driver;
- FT_DriverInterface* interface;
+ FT_Error error;
+ FT_Memory memory;
+ FT_Driver driver;
+ FT_Driver_Class* clazz;
- FT_Size size = 0;
- FT_ListNode node = 0;
+ FT_Size size = 0;
+ FT_ListNode node = 0;
-
- if ( !face )
- return FT_Err_Invalid_Face_Handle;
-
- if ( !asize )
- return FT_Err_Invalid_Argument;
-
*asize = 0;
+ if ( !face || !asize || !face->driver )
+ return FT_Err_Invalid_Handle;
+
driver = face->driver;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
+ clazz = driver->clazz;
+ memory = face->memory;
- interface = &driver->interface;
- memory = face->memory;
-
/* Allocate new size object and perform basic initialisation */
- if ( ALLOC( size, interface->size_object_size ) ||
- ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
+ if ( ALLOC( size, clazz->size_object_size ) ||
+ ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
goto Exit;
size->face = face;
- error = interface->init_size( size );
+ if (clazz->init_size)
+ error = clazz->init_size( size );
/* in case of success, add to the face's list */
if ( !error )
@@ -1571,9 +1650,6 @@
*asize = size;
node->data = size;
FT_List_Add( &face->sizes_list, node );
-
- /* record as current size for the face */
- face->size = size;
}
Exit:
@@ -1621,7 +1697,7 @@
if ( !driver )
return FT_Err_Invalid_Driver_Handle;
- memory = driver->memory;
+ memory = driver->root.memory;
error = FT_Err_Ok;
node = FT_List_Find( &face->sizes_list, size );
@@ -1680,6 +1756,27 @@
/* When dealing with fixed-size faces (i.e., non-scalable formats), */
/* use the function FT_Set_Pixel_Sizes(). */
/* */
+
+ static void ft_recompute_scaled_metrics( FT_Face face,
+ FT_Size_Metrics* metrics )
+ {
+ /* Compute root ascender, descender, test height, and max_advance */
+ metrics->ascender = ( FT_MulFix( face->ascender,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->descender = ( FT_MulFix( face->descender,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->height = ( FT_MulFix( face->height,
+ metrics->y_scale ) + 32 ) & -64;
+
+ metrics->max_advance = ( FT_MulFix( face->max_advance_width,
+ metrics->x_scale ) + 32 ) & -64;
+ }
+
+
+
+
FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face,
FT_F26Dot6 char_width,
FT_F26Dot6 char_height,
@@ -1686,39 +1783,35 @@
FT_UInt horz_resolution,
FT_UInt vert_resolution )
{
- FT_Error error;
- FT_Driver driver;
- FT_Memory memory;
- FT_DriverInterface* interface;
- FT_Size_Metrics* metrics;
- FT_Long dim_x, dim_y;
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Size_Metrics* metrics;
+ FT_Long dim_x, dim_y;
- if ( !face )
+ if ( !face || !face->size || !face->driver )
return FT_Err_Invalid_Face_Handle;
- if ( !face->size )
- return FT_Err_Invalid_Size_Handle;
-
- driver = face->driver;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
-
+ driver = face->driver;
metrics = &face->size->metrics;
if ( !char_width )
char_width = char_height;
+
else if ( !char_height )
char_height = char_width;
if ( !horz_resolution )
horz_resolution = 72;
+
if ( !vert_resolution )
vert_resolution = 72;
- driver = face->driver;
- interface = &driver->interface;
- memory = driver->memory;
+ driver = face->driver;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
/* default processing -- this can be overridden by the driver */
if ( char_width < 1 * 64 ) char_width = 1 * 64;
@@ -1740,11 +1833,14 @@
metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
}
- error = interface->set_char_sizes( face->size,
- char_width,
- char_height,
- horz_resolution,
- vert_resolution );
+ ft_recompute_scaled_metrics( face, metrics );
+
+ if (clazz->set_char_sizes)
+ error = clazz->set_char_sizes( face->size,
+ char_width,
+ char_height,
+ horz_resolution,
+ vert_resolution );
return error;
}
@@ -1776,29 +1872,24 @@
FT_UInt pixel_width,
FT_UInt pixel_height )
{
- FT_Error error;
- FT_Driver driver;
- FT_Memory memory;
- FT_DriverInterface* interface;
- FT_Size_Metrics* metrics = &face->size->metrics;
+ FT_Error error = FT_Err_Ok;
+ FT_Driver driver;
+ FT_Memory memory;
+ FT_Driver_Class* clazz;
+ FT_Size_Metrics* metrics = &face->size->metrics;
- if ( !face )
+ if ( !face || !face->size || !face->driver )
return FT_Err_Invalid_Face_Handle;
- if ( !face->size )
- return FT_Err_Invalid_Size_Handle;
-
driver = face->driver;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
+ clazz = driver->clazz;
+ memory = driver->root.memory;
- interface = &driver->interface;
- memory = driver->memory;
-
/* default processing -- this can be overridden by the driver */
if ( pixel_width == 0 )
pixel_width = pixel_height;
+
else if ( pixel_height == 0 )
pixel_height = pixel_width;
@@ -1817,82 +1908,12 @@
face->units_per_EM );
}
- error = interface->set_pixel_sizes( face->size,
- pixel_width,
- pixel_height );
- return error;
- }
+ ft_recompute_scaled_metrics( face, metrics );
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_New_GlyphSlot */
- /* */
- /* <Description> */
- /* It is sometimes useful to have more than one glyph slot for a */
- /* given face object. This function is used to create additional */
- /* slots. All of them are automatically discarded when the face is */
- /* destroyed. */
- /* */
- /* <Input> */
- /* face :: A handle to a parent face object. */
- /* */
- /* <Output> */
- /* aslot :: A handle to a new glyph slot object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
- FT_GlyphSlot* aslot )
- {
- FT_Error error;
- FT_Driver driver;
- FT_DriverInterface* interface;
- FT_Memory memory;
- FT_GlyphSlot slot;
-
-
- if ( !face )
- return FT_Err_Invalid_Face_Handle;
-
- if ( !aslot )
- return FT_Err_Invalid_Argument;
-
- *aslot = 0;
-
- driver = face->driver;
- if ( !driver )
- return FT_Err_Invalid_Driver_Handle;
-
- interface = &driver->interface;
- memory = driver->memory;
-
- FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
- if ( ALLOC( slot, interface->slot_object_size ) )
- goto Exit;
-
- slot->face = face;
-
- slot->max_subglyphs = 0;
- slot->num_subglyphs = 0;
- slot->subglyphs = 0;
-
- error = interface->init_glyph_slot( slot );
- if ( !error )
- {
- /* in case of success, add slot to the face's list */
- slot->next = face->glyph;
- face->glyph = slot;
- *aslot = slot;
- }
-
- if ( error )
- FREE( slot );
-
- Exit:
- FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
+ if (clazz->set_pixel_sizes)
+ error = clazz->set_pixel_sizes( face->size,
+ pixel_width,
+ pixel_height );
return error;
}
@@ -1900,166 +1921,6 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Done_GlyphSlot */
- /* */
- /* <Description> */
- /* Destroys a given glyph slot. Remember however that all slots are */
- /* automatically destroyed with its parent. Using this function is */
- /* not always mandatory. */
- /* */
- /* <Input> */
- /* slot :: A handle to a target glyph slot. */
- /* */
- FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
- {
- if ( slot )
- {
- FT_Driver driver = slot->face->driver;
- FT_Memory memory = driver->memory;
- FT_GlyphSlot* parent;
- FT_GlyphSlot cur;
-
-
- /* Remove slot from its parent face's list */
- parent = &slot->face->glyph;
- cur = *parent;
- while ( cur )
- {
- if ( cur == slot )
- {
- *parent = cur->next;
- break;
- }
- cur = cur->next;
- }
-
- driver->interface.done_glyph_slot( slot );
- FREE( slot );
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Load_Glyph */
- /* */
- /* <Description> */
- /* A function used to load a single glyph within a given face. */
- /* */
- /* <Input> */
- /* face :: A handle to a target face object where the glyph */
- /* will be 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). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
- FT_UInt glyph_index,
- FT_Int load_flags )
- {
- FT_Error error;
- FT_Driver driver;
-
-
- if ( !face )
- return FT_Err_Invalid_Face_Handle;
-
- if ( !face->size )
- return FT_Err_Invalid_Size_Handle;
-
- if ( !face->glyph )
- return FT_Err_Invalid_Slot_Handle;
-
- if ( glyph_index >= face->num_glyphs )
- return FT_Err_Invalid_Argument;
-
- driver = face->driver;
-
- /* when the flag NO_RECURSE is set, we disable hinting and scaling */
- if ( load_flags & FT_LOAD_NO_RECURSE )
- load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-
- error = driver->interface.load_glyph( face->glyph,
- face->size,
- glyph_index,
- load_flags );
-
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Load_Char */
- /* */
- /* <Description> */
- /* A function used to load a single character within a given face */
- /* and the selected charmap (to be done with the FT_Select_Charmap() */
- /* function). */
- /* */
- /* <Input> */
- /* face :: A handle to a target face object where the */
- /* character will be loaded. */
- /* */
- /* char_code :: The character code 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). */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
- FT_ULong char_code,
- FT_Int load_flags )
- {
- FT_Error error;
- FT_Driver driver;
- FT_UInt glyph_index;
-
-
- if ( !face )
- return FT_Err_Invalid_Face_Handle;
-
- if ( !face->size )
- return FT_Err_Invalid_Size_Handle;
-
- if ( !face->glyph )
- return FT_Err_Invalid_Slot_Handle;
-
- if ( !face->charmap )
- return FT_Err_Invalid_CharMap_Handle;
-
- driver = face->driver;
- glyph_index = FT_Get_Char_Index( face, char_code );
-
- if ( glyph_index == 0 )
- error = FT_Err_Invalid_Character_Code;
- else
- error = driver->interface.load_glyph( face->glyph,
- face->size,
- glyph_index,
- load_flags );
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
/* FT_Get_Kerning */
/* */
/* <Description> */
@@ -2103,11 +1964,11 @@
return FT_Err_Invalid_Argument;
driver = face->driver;
- memory = driver->memory;
+ memory = driver->root.memory;
- if ( driver->interface.get_kerning )
+ if ( driver->clazz->get_kerning )
{
- error = driver->interface.get_kerning( face,
+ error = driver->clazz->get_kerning( face,
left_glyph,
right_glyph,
kerning );
@@ -2247,7 +2108,7 @@
if ( face && face->charmap )
{
driver = face->driver;
- result = driver->interface.get_char_index( face->charmap, charcode );
+ result = driver->clazz->get_char_index( face->charmap, charcode );
}
return result;
}
@@ -2291,8 +2152,8 @@
goto Exit;
driver = face->driver;
- func = (FT_Get_Sfnt_Table_Func)driver->interface.get_interface(
- driver, "get_sfnt" );
+ func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
+ FT_MODULE(driver), "get_sfnt" );
if ( func )
table = func( face, tag );
@@ -2299,6 +2160,764 @@
Exit:
return table;
}
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** R E N D E R E R S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* lookup a renderer by glyph format in the library's list */
+ static FT_Renderer ft_lookup_renderer( FT_Library library,
+ FT_Glyph_Format format,
+ FT_ListNode *node )
+ {
+ FT_ListNode cur = library->renderers.head;
+ FT_Renderer result = 0;
+
+ if (node)
+ *node = 0;
+
+ while (cur)
+ {
+ FT_Renderer renderer = FT_RENDERER(cur->data);
+
+ if (renderer->glyph_format == format)
+ {
+ if (node)
+ *node = cur;
+
+ result = renderer;
+ break;
+ }
+
+ }
+ return result;
+ }
+
+
+ static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot )
+ {
+ FT_Face face = slot->face;
+ FT_Library library = FT_FACE_LIBRARY(face);
+ FT_Renderer result = library->cur_renderer;
+
+ if (!result || result->glyph_format != slot->format)
+ result = ft_lookup_renderer( library, slot->format, 0 );
+
+ return result;
+ }
+
+
+ static void ft_set_current_renderer( FT_Library library )
+ {
+ FT_Renderer renderer;
+
+ renderer = ft_lookup_renderer( library, ft_glyph_format_outline, 0 );
+ library->cur_renderer = renderer;
+ }
+
+
+ static FT_Error ft_add_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+ FT_ListNode node;
+
+ if (ALLOC(node,sizeof(*node)))
+ goto Exit;
+
+ {
+ FT_Renderer render = FT_RENDERER(module);
+ FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
+
+ render->clazz = clazz;
+ render->glyph_format = clazz->glyph_format;
+
+ /* allocate raster object if needed */
+ if ( clazz->glyph_format == ft_glyph_format_outline &&
+ clazz->raster_class->raster_new )
+ {
+ error = clazz->raster_class->raster_new( memory, &render->raster );
+ if (error) goto Fail;
+
+ render->raster_render = clazz->raster_class->raster_render;
+ render->render = clazz->render_glyph;
+ }
+
+ /* add to list */
+ node->data = module;
+ FT_List_Add( &library->renderers, node );
+
+ ft_set_current_renderer( library );
+ }
+
+ Fail:
+ if (error)
+ FREE(node);
+
+ Exit:
+ return error;
+ }
+
+
+ static void ft_remove_renderer( FT_Module module )
+ {
+ FT_Library library = module->library;
+ FT_Memory memory = library->memory;
+ FT_ListNode node;
+
+ node = FT_List_Find( &library->renderers, module );
+ if (node)
+ {
+ FT_Renderer render = FT_RENDERER(module);
+
+ /* release raster object, if any */
+ if (render->raster)
+ render->clazz->raster_class->raster_done( render->raster );
+
+ /* remove from list */
+ FT_List_Remove( &library->renderers, node );
+ FREE( node );
+
+ ft_set_current_renderer( library );
+ }
+ }
+
+
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Get_Renderer
+ *
+ * <Description>
+ * retrieves the current renderer for a given glyph format.
+ *
+ * <Input>
+ * library :: handle to library object
+ * format :: glyph format
+ *
+ * <Return>
+ * renderer handle. 0 if none found.
+ *
+ * <Note>
+ * An error will be returned if a module already exists by that
+ * name, or if the module requires a version of freetype that is
+ * too great
+ *
+ * To add a new renderer, simply use FT_Add_Module. To retrieve
+ * a renderer by its name, use FT_Get_Module
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(FT_Renderer) FT_Get_Renderer( FT_Library library,
+ FT_Glyph_Format format )
+ {
+ return ft_lookup_renderer( library, format, 0 );
+ }
+
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Set_Renderer
+ *
+ * <Description>
+ * Sets the current renderer to use, and set additional mode
+ *
+ * <Input>
+ * library :: handle to library object
+ * renderer :: handle to renderer object
+ * num_params :: number of additional parameters
+ * params :: additional parameters
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ * <Note>
+ * in case of success, the renderer will be used to convert glyph
+ * images in the renderer's known format into bitmaps.
+ *
+ * This doesn't change the current renderer for other formats..
+ *
+ *************************************************************************/
+
+ FT_EXPORT_DEF(FT_Error) FT_Set_Renderer( FT_Library library,
+ FT_Renderer renderer,
+ FT_UInt num_params,
+ FT_Parameter* parameters )
+ {
+ FT_ListNode node;
+ FT_Error error = FT_Err_Ok;
+
+ node = FT_List_Find( &library->renderers, renderer );
+ if (!node)
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ FT_List_Up( &library->renderers, node );
+
+ if (renderer->glyph_format == ft_glyph_format_outline )
+ library->cur_renderer = renderer;
+
+ if (num_params > 0)
+ {
+ FTRenderer_setMode set_mode = renderer->clazz->set_mode;
+
+ for ( ; num_params > 0; num_params-- )
+ {
+ error = set_mode( renderer, parameters->tag, parameters->data );
+ if (error)
+ break;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Render_Glyph
+ *
+ * <Description>
+ * Converts a given glyph image to a bitmap. It does so by inspecting
+ * the glyph image format, find the relevant renderer, and invoke it
+ *
+ * <Input>
+ * slot :: handle to the glyph slot containing the image to
+ * convert
+ *
+ * render_mode :: a set of bit flags indicating which kind of bitmap
+ * to render. For now, only 'ft_render_mode_anti_alias'
+ * is supported by the available renderers, but others
+ * could appear later (e.g. LCD or TV optimised)
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ * <Note>
+ * in case of success, the renderer will be used to convert glyph
+ * images in the renderer's known format into bitmaps.
+ *
+ * This doesn't change the current renderer for other formats..
+ *
+ * The slot's native image should be considered lost after the
+ * conversion..
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(FT_Error) FT_Render_Glyph( FT_GlyphSlot slot,
+ FT_UInt render_mode )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_Renderer renderer;
+
+ if (slot)
+ {
+ FT_Face face = slot->face;
+ FT_Library library = FT_FACE_LIBRARY(face);
+
+ /* if it's already a bitmap, no need to do anything */
+ switch (slot->format)
+ {
+ case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
+ break;
+
+ default:
+ {
+ /* small shortcut for the very common case */
+ if (slot->format == ft_glyph_format_outline)
+ renderer = library->cur_renderer;
+ else
+ renderer = ft_lookup_renderer( library, slot->format, 0 );
+
+ error = FT_Err_Unimplemented_Feature;
+ if (renderer)
+ error = renderer->render( renderer, slot, render_mode );
+ }
+ }
+ }
+ else
+ error = FT_Err_Invalid_Argument;
+
+ return error;
+ }
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** M O D U L E S ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Destroy_Module */
+ /* */
+ /* <Description> */
+ /* Destroys a given module object. For drivers, this also destroys */
+ /* all child faces.. */
+ /* */
+ /* <InOut> */
+ /* module :: A handle to the target driver object. */
+ /* */
+ /* <Note> */
+ /* The driver _must_ be LOCKED! */
+ /* */
+ static
+ void Destroy_Module( FT_Module module )
+ {
+ FT_Memory memory = module->memory;
+ FT_Module_Class* clazz = module->clazz;
+
+ /* finalize client-data - before anything else */
+ if ( module->generic.finalizer )
+ module->generic.finalizer( module );
+
+ /* if the module is a renderer */
+ if (FT_MODULE_IS_RENDERER(module))
+ ft_remove_renderer(module);
+
+ /* if the module is a font driver, add some steps */
+ if (FT_MODULE_IS_DRIVER(module))
+ Destroy_Driver( FT_DRIVER(module) );
+
+ /* finalize the module object */
+ if (clazz->module_done)
+ clazz->module_done(module);
+
+ /* discard it */
+ FREE( module );
+ }
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Add_Module
+ *
+ * <Description>
+ * Add a new module to a given library instance.
+ *
+ * <Input>
+ * library :: handle to library object
+ * clazz :: pointer to class descriptor for the module
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ * <Note>
+ * An error will be returned if a module already exists by that
+ * name, or if the module requires a version of freetype that is
+ * too great
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(FT_Error) FT_Add_Module( FT_Library library,
+ const FT_Module_Class* clazz )
+ {
+ FT_Error error;
+ FT_Memory memory;
+ FT_Module module;
+ FT_UInt nn;
+
+ #define FREETYPE_VER_FIXED (((FT_Long)FREETYPE_MAJOR << 16) | FREETYPE_MINOR)
+
+ if (!library || !clazz)
+ return FT_Err_Invalid_Argument;
+
+ /* check freetype version */
+ if ( clazz->module_requires > FREETYPE_VER_FIXED )
+ return FT_Err_Invalid_Version;
+
+ /* look for a module with the same name in the library's table */
+ for ( nn = 0; nn < library->num_modules; nn++ )
+ {
+ module = library->modules[nn];
+ if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
+ {
+ /* this installed module has the same name, compare their versions */
+ if ( clazz->module_version <= module->clazz->module_version )
+ return FT_Err_Lower_Module_Version;
+
+ /* remove the module from our list, then exit the loop to replace */
+ /* it by our new version.. */
+ FT_Remove_Module( library, module );
+ break;
+ }
+ }
+
+ memory = library->memory;
+ error = FT_Err_Ok;
+
+ if ( library->num_modules >= FT_MAX_MODULES )
+ {
+ error = FT_Err_Too_Many_Drivers;
+ goto Exit;
+ }
+
+ /* allocate module object */
+ if (ALLOC(module,clazz->module_size))
+ goto Exit;
+
+ /* base initialisation */
+ module->library = library;
+ module->memory = memory;
+ module->clazz = (FT_Module_Class*)clazz;
+
+ /* if the module is a renderer - this must be performed before */
+ /* the normal module initialisation.. */
+ if (FT_MODULE_IS_RENDERER(module))
+ {
+ /* add to the renderers list */
+ error = ft_add_renderer(module);
+ if (error) goto Fail;
+ }
+
+ /* if the module is a font driver */
+ if (FT_MODULE_IS_DRIVER(module))
+ {
+ /* allocate glyph loader if needed */
+ FT_Driver driver = FT_DRIVER(module);
+
+ driver->clazz = (FT_Driver_Class*)module->clazz;
+ if (FT_DRIVER_USES_OUTLINES(driver))
+ {
+ error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
+ if (error) goto Fail;
+ }
+ }
+
+ if (clazz->module_init)
+ {
+ error = clazz->module_init(module);
+ if (error) goto Fail;
+ }
+
+ /* add module to the library's table */
+ library->modules[ library->num_modules++ ] = module;
+
+
+ Exit:
+ return error;
+
+ Fail:
+ if (FT_MODULE_IS_DRIVER(module))
+ {
+ FT_Driver driver = FT_DRIVER(module);
+
+ if (FT_DRIVER_USES_OUTLINES(driver))
+ FT_GlyphLoader_Done( driver->glyph_loader );
+ }
+
+ if (FT_MODULE_IS_RENDERER(module))
+ {
+ FT_Renderer renderer = FT_RENDERER(module);
+ if (renderer->raster)
+ renderer->clazz->raster_class->raster_done( renderer->raster );
+ }
+ FREE(module);
+ goto Exit;
+ }
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Get_Module
+ *
+ * <Description>
+ * Find a module by its name.
+ *
+ * <Input>
+ * library :: handle to library object
+ * module_name :: the module's ASCII name.
+ *
+ * <Return>
+ * Module handle, 0 if none was found.
+ *
+ * <Note>
+ * You'd better be familiar with FreeType internals to know which
+ * module to look for :-)
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(FT_Module) FT_Get_Module( FT_Library library,
+ const char* module_name )
+ {
+ FT_Module result = 0;
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+ for ( ; cur < limit; cur++ )
+ if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
+ {
+ result = cur[0];
+ break;
+ }
+
+ return result;
+ }
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Get_Module_Interface
+ *
+ * <Description>
+ * Find a module and returns it's specific interface as a void*
+ *
+ * <Input>
+ * library :: handle to library object
+ * module_name :: the module's ASCII name.
+ *
+ * <Return>
+ * Module specific interface, if any
+ *
+ * <Note>
+ * You'd better be familiar with FreeType internals to know which
+ * module to look for, and what it's interface is :-)
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(const void*) FT_Get_Module_Interface( FT_Library library,
+ const char* mod_name )
+ {
+ FT_Module module;
+
+ module = FT_Get_Module( library, mod_name );
+ return module ? module->clazz->module_interface : 0;
+ }
+
+
+ /*************************************************************************
+ *
+ * <Function>
+ * FT_Remove_Module
+ *
+ * <Description>
+ * Removes a given module from a library instance.
+ *
+ * <Input>
+ * library :: handle to library object
+ * module :: handle to module object
+ *
+ * <Return>
+ * Error code (module not listed)
+ *
+ * <Note>
+ * The module object is destroyed by the function in case of success
+ *
+ *************************************************************************/
+
+ FT_EXPORT_FUNC(FT_Error) FT_Remove_Module( FT_Library library,
+ FT_Module module )
+ {
+ /* try to find the module from the table, then remove it from there */
+ if (library && module)
+ {
+ FT_Module* cur = library->modules;
+ FT_Module* limit = cur + library->num_modules;
+
+ for ( ; cur < limit; cur++ )
+ {
+ if (cur[0] == module)
+ {
+ /* remove it from the table */
+ library->num_modules--;
+ limit--;
+ while (cur < limit)
+ {
+ cur[0] = cur[1];
+ cur++;
+ }
+ limit[0] = 0;
+
+ /* destroy the module */
+ Destroy_Module(module);
+
+ return FT_Err_Ok;
+ }
+ }
+ }
+ return FT_Err_Invalid_Handle;
+ }
+
+
+
+
+
+
+
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** ****/
+ /**** L I B R A R Y ****/
+ /**** ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_New_Library */
+ /* */
+ /* <Description> */
+ /* This function is used to create a new FreeType library instance */
+ /* from a given memory object. It is thus possible to use libraries */
+ /* with distinct memory allocators within the same program. */
+ /* */
+ /* <Input> */
+ /* memory :: A handle to the original memory object. */
+ /* */
+ /* <Output> */
+ /* alibrary :: A pointer to handle of a new library object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
+ FT_Library* alibrary )
+ {
+ FT_Library library = 0;
+ FT_Error error;
+
+
+ if ( !memory )
+ return FT_Err_Invalid_Argument;
+
+ /* first of all, allocate the library object */
+ if ( ALLOC( library, sizeof ( *library ) ) )
+ return error;
+
+ library->memory = memory;
+
+ /* allocate the render pool */
+ library->raster_pool_size = FT_RENDER_POOL_SIZE;
+ if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
+ goto Fail;
+
+ /* That's ok now */
+ *alibrary = library;
+
+ return FT_Err_Ok;
+
+ Fail:
+ FREE( library );
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Done_Library */
+ /* */
+ /* <Description> */
+ /* Discards a given library object. This closes all drivers and */
+ /* discards all resource objects. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the target library. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
+ {
+ FT_Memory memory;
+ FT_Int n;
+
+
+ if ( !library )
+ return FT_Err_Invalid_Library_Handle;
+
+ memory = library->memory;
+
+ /* Discard client-data */
+ if ( library->generic.finalizer )
+ library->generic.finalizer( library );
+
+ /* Close all modules in the library */
+ for ( n = 0; n < library->num_modules; n++ )
+ {
+ FT_Module module = library->modules[n];
+
+ if ( module )
+ {
+ Destroy_Module( module );
+ library->modules[n] = 0;
+ }
+ }
+
+ /* Destroy raster objects */
+ FREE( library->raster_pool );
+ library->raster_pool_size = 0;
+
+ FREE( library );
+ return FT_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Set_Debug_Hook */
+ /* */
+ /* <Description> */
+ /* Sets a debug hook function for debugging the interpreter of a */
+ /* font format. */
+ /* */
+ /* <Input> */
+ /* library :: A handle to the library object. */
+ /* */
+ /* hook_index :: The index of the debug hook. You should use the */
+ /* values defined in ftobjs.h, e.g. */
+ /* FT_DEBUG_HOOK_TRUETYPE */
+ /* */
+ /* debug_hook :: The function used to debug the interpreter. */
+ /* */
+ /* <Note> */
+ /* Currently, four debug hook slots are available, but only two (for */
+ /* the TrueType and the Type 1 interpreter) are defined. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
+ FT_UInt hook_index,
+ FT_DebugHook_Func debug_hook )
+ {
+ if ( library && debug_hook &&
+ hook_index <
+ ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
+ library->debug_hooks[hook_index] = debug_hook;
+ }
+
+
+
/*************************************************************************/
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -569,11 +569,12 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Outline_Get_Bitmap */
+ /* FT_Outline_Render */
/* */
/* <Description> */
- /* Renders an outline within a bitmap. The outline's image is simply */
- /* OR-ed to the target bitmap. */
+ /* Renders an outline within a bitmap using the current scan-convert. */
+ /* This functions uses a FT_Raster_Params as argument, allowing */
+ /* advanced features like direct composition/translucency, etc. */
/* */
/* <Input> */
/* library :: A handle to a FreeType library object. */
@@ -580,7 +581,8 @@
/* */
/* outline :: A pointer to the source outline descriptor. */
/* */
- /* map :: A pointer to the target bitmap descriptor. */
+ /* params :: A pointer to a FT_Raster_Params used to describe */
+ /* the rendering operation. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -590,41 +592,45 @@
/* scan-line converter will be serialized. */
/* */
/* <Note> */
- /* This function does NOT CREATE the bitmap, it only renders an */
- /* outline image within the one you pass to it! */
+ /* You should know what you're doing and the role of FT_Raster_Params */
+ /* to use this function. */
/* */
- /* It will use the raster correponding to the default glyph format. */
+ /* The field `params.source' will be set to `outline' before the scan */
+ /* converter is called, which means that the value you give to it is */
+ /* actually ignored. */
/* */
- FT_EXPORT_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library,
- FT_Outline* outline,
- FT_Bitmap* bitmap )
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Render( FT_Library library,
+ FT_Outline* outline,
+ FT_Raster_Params* params )
{
- FT_Error error;
- FT_Raster raster;
- FT_Raster_Funcs funcs;
- FT_Raster_Params params;
+ FT_Error error;
+ FT_Renderer renderer;
-
if ( !library )
- return FT_Err_Invalid_Library_Handle;
+ {
+ error = FT_Err_Invalid_Library_Handle;
+ goto Exit;
+ }
- if ( !outline || !bitmap )
- return FT_Err_Invalid_Argument;
+ if ( !outline || !params )
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
- error = FT_Err_Invalid_Glyph_Format;
- raster = FT_Get_Raster( library, ft_glyph_format_outline, &funcs );
- if ( !raster )
+ /* retrieve the current outline renderer */
+ renderer = library->cur_renderer;
+ if (!renderer)
+ {
+ /* XXXX: should use another error code */
+ error = FT_Err_Invalid_Argument;
goto Exit;
+ }
- params.target = bitmap;
- params.source = outline;
- params.flags = 0;
+ params->source = (void*)outline;
+
+ error = renderer->raster_render( renderer->raster, params );
- if ( bitmap->pixel_mode == ft_pixel_mode_grays )
- params.flags |= ft_raster_flag_aa;
-
- error = funcs.raster_render( raster, ¶ms );
-
Exit:
return error;
}
@@ -633,12 +639,11 @@
/*************************************************************************/
/* */
/* <Function> */
- /* FT_Outline_Render */
+ /* FT_Outline_Get_Bitmap */
/* */
/* <Description> */
- /* Renders an outline within a bitmap using the current scan-convert. */
- /* This functions uses a FT_Raster_Params as argument, allowing */
- /* advanced features like direct composition/translucency, etc. */
+ /* Renders an outline within a bitmap. The outline's image is simply */
+ /* OR-ed to the target bitmap. */
/* */
/* <Input> */
/* library :: A handle to a FreeType library object. */
@@ -645,8 +650,7 @@
/* */
/* outline :: A pointer to the source outline descriptor. */
/* */
- /* params :: A pointer to a FT_Raster_Params used to describe */
- /* the rendering operation. */
+ /* map :: A pointer to the target bitmap descriptor. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
@@ -656,41 +660,72 @@
/* scan-line converter will be serialized. */
/* */
/* <Note> */
- /* You should know what you're doing and the role of FT_Raster_Params */
- /* to use this function. */
+ /* This function does NOT CREATE the bitmap, it only renders an */
+ /* outline image within the one you pass to it! */
/* */
- /* The field `params.source' will be set to `outline' before the scan */
- /* converter is called, which means that the value you give to it is */
- /* actually ignored. */
+ /* It will use the raster correponding to the default glyph format. */
/* */
- FT_EXPORT_FUNC( FT_Error ) FT_Outline_Render( FT_Library library,
- FT_Outline* outline,
- FT_Raster_Params* params )
+ FT_EXPORT_FUNC( FT_Error ) FT_Outline_Get_Bitmap( FT_Library library,
+ FT_Outline* outline,
+ FT_Bitmap* bitmap )
{
- FT_Error error;
- FT_Raster raster;
- FT_Raster_Funcs funcs;
+ FT_Raster_Params params;
+ if (!bitmap)
+ return FT_Err_Invalid_Argument;
- if ( !library )
- return FT_Err_Invalid_Library_Handle;
+ /* other checks are delayed to FT_Outline_Render */
- if ( !outline || !params )
- return FT_Err_Invalid_Argument;
+ params.target = bitmap;
+ params.flags = 0;
- error = FT_Err_Invalid_Glyph_Format;
- raster = FT_Get_Raster( library, ft_glyph_format_outline, &funcs );
- if ( !raster )
- goto Exit;
+ if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+ params.flags |= ft_raster_flag_aa;
- params->source = (void*)outline;
- error = funcs.raster_render( raster, params );
+ return FT_Outline_Render( library, outline, ¶ms );
+ }
- Exit:
- return error;
+
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Vector_Transform */
+ /* */
+ /* <Description> */
+ /* Transforms a single vector through a 2x2 matrix. */
+ /* */
+ /* <InOut> */
+ /* vector :: The target vector to transform. */
+ /* */
+ /* <Input> */
+ /* matrix :: A pointer to the source 2x2 matrix. */
+ /* */
+ /* <MT-Note> */
+ /* Yes. */
+ /* */
+ /* <Note> */
+ /* The result is undefined if either `vector' or `matrix' is invalid. */
+ /* */
+ FT_EXPORT_FUNC( void ) FT_Vector_Transform( FT_Vector* vector,
+ FT_Matrix* matrix )
+ {
+ FT_Pos xz, yz;
+
+ xz = FT_MulFix( vector->x, matrix->xx ) +
+ FT_MulFix( vector->y, matrix->xy );
+
+ yz = FT_MulFix( vector->x, matrix->yx ) +
+ FT_MulFix( vector->y, matrix->yy );
+
+ vector->x = xz;
+ vector->y = yz;
}
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -715,26 +750,11 @@
BASE_FUNC( void ) FT_Outline_Transform( FT_Outline* outline,
FT_Matrix* matrix )
{
- FT_UShort n;
- FT_Vector* vec;
-
-
- vec = outline->points;
- for ( n = 0; n < outline->n_points; n++ )
- {
- FT_Pos x, y;
-
-
- x = FT_MulFix( vec->x, matrix->xx ) +
- FT_MulFix( vec->y, matrix->xy );
-
- y = FT_MulFix( vec->x, matrix->yx ) +
- FT_MulFix( vec->y, matrix->yy );
-
- vec->x = x;
- vec->y = y;
- vec++;
- }
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+ for ( ; vec < limit; vec++ )
+ FT_Vector_Transform( vec, matrix );
}
@@ -804,46 +824,6 @@
target->flags |= is_owner;
return FT_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* FT_Vector_Transform */
- /* */
- /* <Description> */
- /* Transforms a single vector through a 2x2 matrix. */
- /* */
- /* <InOut> */
- /* vector :: The target vector to transform. */
- /* */
- /* <Input> */
- /* matrix :: A pointer to the source 2x2 matrix. */
- /* */
- /* <MT-Note> */
- /* Yes. */
- /* */
- /* <Note> */
- /* The result is undefined if either `vector' or `matrix' is invalid. */
- /* */
- FT_EXPORT_FUNC( void ) FT_Vector_Transform( FT_Vector* vector,
- FT_Matrix* matrix )
- {
- FT_Pos xz, yz;
-
-
- if ( !vector || !matrix )
- return;
-
- xz = FT_MulFix( vector->x, matrix->xx ) +
- FT_MulFix( vector->y, matrix->xy );
-
- yz = FT_MulFix( vector->x, matrix->yx ) +
- FT_MulFix( vector->y, matrix->yy );
-
- vector->x = xz;
- vector->y = yz;
}
--- a/src/base/ftraster.c
+++ /dev/null
@@ -1,3262 +1,0 @@
-/***************************************************************************/
-/* */
-/* ftraster.c */
-/* */
-/* The FreeType glyph rasterizer (body). */
-/* */
-/* Copyright 1996-2000 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
- /*************************************************************************/
- /* */
- /* This is a rewrite of the FreeType 1.x scan-line converter */
- /* */
- /*************************************************************************/
-
-
-#include <freetype/ftraster.h>
-#include <freetype/internal/ftcalc.h> /* for FT_MulDiv() only */
-
-
- /*************************************************************************/
- /* */
- /* A simple technical note on how the raster works: */
- /* */
- /* Converting an outline into a bitmap is achieved in several steps: */
- /* */
- /* 1 - Decomposing the outline into successive `profiles'. Each */
- /* profile is simply an array of scanline intersections on a given */
- /* dimension. A profile's main attributes are */
- /* */
- /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */
- /* */
- /* o an array of intersection coordinates for each scanline */
- /* between `Ymin' and `Ymax'. */
- /* */
- /* o a direction, indicating whether it was built going `up' or */
- /* `down', as this is very important for filling rules. */
- /* */
- /* 2 - Sweeping the target map's scanlines in order to compute segment */
- /* `spans' which are then filled. Additionally, this pass */
- /* performs drop-out control. */
- /* */
- /* The outline data is parsed during step 1 only. The profiles are */
- /* built from the bottom of the render pool, used as a stack. The */
- /* following graphics shows the profile list under construction: */
- /* */
- /* ____________________________________________________________ _ _ */
- /* | | | | | */
- /* | profile | coordinates for | profile | coordinates for |--> */
- /* | 1 | profile 1 | 2 | profile 2 |--> */
- /* |_________|___________________|_________|_________________|__ _ _ */
- /* */
- /* ^ ^ */
- /* | | */
- /* start of render pool top */
- /* */
- /* The top of the profile stack is kept in the `top' variable. */
- /* */
- /* As you can see, a profile record is pushed on top of the render */
- /* pool, which is then followed by its coordinates/intersections. If */
- /* a change of direction is detected in the outline, a new profile is */
- /* generated until the end of the outline. */
- /* */
- /* Note that when all profiles have been generated, the function */
- /* Finalize_Profile_Table() is used to record, for each profile, its */
- /* bottom-most scanline as well as the scanline above its upmost */
- /* boundary. These positions are called `y-turns' because they (sort */
- /* of) correspond to local extrema. They are stored in a sorted list */
- /* built from the top of the render pool as a downwards stack: */
- /* */
- /* _ _ _______________________________________ */
- /* | | */
- /* <--| sorted list of | */
- /* <--| extrema scanlines | */
- /* _ _ __________________|____________________| */
- /* */
- /* ^ ^ */
- /* | | */
- /* maxBuff sizeBuff = end of pool */
- /* */
- /* This list is later used during the sweep phase in order to */
- /* optimize performance (see technical note on the sweep below). */
- /* */
- /* Of course, the raster detects whether the two stacks collide and */
- /* handles the situation propertly. */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /*************************************************************************/
- /** **/
- /** CONFIGURATION MACROS **/
- /** **/
- /*************************************************************************/
- /*************************************************************************/
-
- /* define DEBUG_RASTER if you want to compile a debugging version */
-#define xxxDEBUG_RASTER
-
- /* The default render pool size in bytes */
-#define RASTER_RENDER_POOL 8192
-
- /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
- /* 5-levels anti-aliasing */
-#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
-#define FT_RASTER_OPTION_ANTI_ALIASING
-#endif
-
- /* The size of the two-lines intermediate bitmap used */
- /* for anti-aliasing, in bytes. */
-#define RASTER_GRAY_LINES 2048
-
-
- /*************************************************************************/
- /*************************************************************************/
- /** **/
- /** OTHER MACROS (do not change) **/
- /** **/
- /*************************************************************************/
- /*************************************************************************/
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_raster
-
-
-#ifdef _STANDALONE_
-
-
- /* This macro is used to indicate that a function parameter is unused. */
- /* Its purpose is simply to reduce compiler warnings. Note also that */
- /* simply defining it as `(void)x' doesn't avoid warnings with certain */
- /* ANSI compilers (e.g. LCC). */
-#define UNUSED( x ) (x) = (x)
-
- /* Disable the tracing mechanism for simplicity -- developers can */
- /* activate it easily by redefining these two macros. */
-#ifndef FT_ERROR
-#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-#ifndef FT_TRACE
-#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-
-#else /* _STANDALONE_ */
-
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
-
-
-#endif /* _STANDALONE_ */
-
-
-#define Raster_Err_None 0
-#define Raster_Err_Not_Ini -1
-#define Raster_Err_Overflow -2
-#define Raster_Err_Neg_Height -3
-#define Raster_Err_Invalid -4
-#define Raster_Err_Gray_Unsupported -5
-#define Raster_Err_Unsupported -6
-
- /* FMulDiv means `Fast MulDiv', it is used in case where `b' is */
- /* typically a small value and the result of a*b is known to fit into */
- /* 32 bits. */
-#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
-
- /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
- /* for clipping computations. It simply uses the FT_MulDiv() function */
- /* defined in `ftcalc.h'. */
-#define SMulDiv FT_MulDiv
-
- /* The rasterizer is a very general purpose component; please leave */
- /* the following redefinitions there (you never know your target */
- /* environment). */
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef NULL
-#define NULL (void*)0
-#endif
-
-#ifndef SUCCESS
-#define SUCCESS 0
-#endif
-
-#ifndef FAILURE
-#define FAILURE 1
-#endif
-
-
-#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
- /* Setting this constant to more than 32 is a */
- /* pure waste of space. */
-
-#define Pixel_Bits 6 /* fractional bits of *input* coordinates */
-
-
- /*************************************************************************/
- /*************************************************************************/
- /** **/
- /** SIMPLE TYPE DECLARATIONS **/
- /** **/
- /*************************************************************************/
- /*************************************************************************/
-
- typedef int Int;
- typedef unsigned int UInt;
- typedef short Short;
- typedef unsigned short UShort, *PUShort;
- typedef long Long, *PLong;
- typedef unsigned long ULong;
-
- typedef unsigned char Byte, *PByte;
- typedef char Bool;
-
- typedef struct TPoint_
- {
- Long x;
- Long y;
-
- } TPoint;
-
-
- typedef enum TFlow_
- {
- Flow_None = 0,
- Flow_Up = 1,
- Flow_Down = -1
-
- } TFlow;
-
-
- /* States of each line, arc, and profile */
- typedef enum TStates_
- {
- Unknown,
- Ascending,
- Descending,
- Flat
-
- } TStates;
-
-
- typedef struct TProfile_ TProfile;
- typedef TProfile* PProfile;
-
- struct TProfile_
- {
- FT_F26Dot6 X; /* current coordinate during sweep */
- PProfile link; /* link to next profile - various purpose */
- PLong offset; /* start of profile's data in render pool */
- Int flow; /* Profile orientation: Asc/Descending */
- Long height; /* profile's height in scanlines */
- Long start; /* profile's starting scanline */
-
- UShort countL; /* number of lines to step before this */
- /* profile becomes drawable */
-
- PProfile next; /* next profile in same contour, used */
- /* during drop-out control */
- };
-
- typedef PProfile TProfileList;
- typedef PProfile* PProfileList;
-
-
- /* Simple record used to implement a stack of bands, required */
- /* by the sub-banding mechanism */
- typedef struct TBand_
- {
- Short y_min; /* band's minimum */
- Short y_max; /* band's maximum */
-
- } TBand;
-
-
-#define AlignProfileSize \
- ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
-
-
-#ifdef TT_STATIC_RASTER
-
-#define RAS_ARGS /* void */
-#define RAS_ARG /* void */
-
-#define RAS_VARS /* void */
-#define RAS_VAR /* void */
-
-#define UNUSED_RASTER do ; while ( 0 )
-
-#else /* TT_STATIC_RASTER */
-
-#define RAS_ARGS TRaster_Instance* raster,
-#define RAS_ARG TRaster_Instance* raster
-
-#define RAS_VARS raster,
-#define RAS_VAR raster
-
-#define UNUSED_RASTER UNUSED( raster )
-
-#endif /* TT_STATIC_RASTER */
-
-
- typedef struct TRaster_Instance_ TRaster_Instance;
-
-
- /* prototypes used for sweep function dispatch */
- typedef void Function_Sweep_Init( RAS_ARGS Short* min,
- Short* max );
-
- typedef void Function_Sweep_Span( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right );
-
- typedef void Function_Sweep_Step( RAS_ARG );
-
-
- /* NOTE: These operations are only valid on 2's complement processors */
-
-#define FLOOR( x ) ( (x) & -ras.precision )
-#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
-#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
-#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
-
- /* Note that I have moved the location of some fields in the */
- /* structure to ensure that the most used variables are used */
- /* at the top. Thus, their offset can be coded with less */
- /* opcodes, and it results in a smaller executable. */
-
- struct TRaster_Instance_
- {
- Int precision_bits; /* precision related variables */
- Int precision;
- Int precision_half;
- Long precision_mask;
- Int precision_shift;
- Int precision_step;
- Int precision_jitter;
-
- Int scale_shift; /* == precision_shift for bitmaps */
- /* == precision_shift+1 for pixmaps */
-
- PLong buff; /* The profiles buffer */
- PLong sizeBuff; /* Render pool size */
- PLong maxBuff; /* Profiles buffer size */
- PLong top; /* Current cursor in buffer */
-
- FT_Error error;
-
- Int numTurns; /* number of Y-turns in outline */
-
- TPoint* arc; /* current Bezier arc pointer */
-
- UShort bWidth; /* target bitmap width */
- PByte bTarget; /* target bitmap buffer */
- PByte gTarget; /* target pixmap buffer */
-
- Long lastX, lastY, minY, maxY;
-
- UShort num_Profs; /* current number of profiles */
-
- Bool fresh; /* signals a fresh new profile which */
- /* 'start' field must be completed */
- Bool joint; /* signals that the last arc ended */
- /* exactly on a scanline. Allows */
- /* removal of doublets */
- PProfile cProfile; /* current profile */
- PProfile fProfile; /* head of linked list of profiles */
- PProfile gProfile; /* contour's first profile in case */
- /* of impact */
- TStates state; /* rendering state */
-
- FT_Bitmap target; /* description of target bit/pixmap */
- FT_Outline outline;
-
- Long traceOfs; /* current offset in target bitmap */
- Long traceG; /* current offset in target pixmap */
-
- Short traceIncr; /* sweep's increment in target bitmap */
-
- Short gray_min_x; /* current min x during gray rendering */
- Short gray_max_x; /* current max x during gray rendering */
-
- /* dispatch variables */
-
- Function_Sweep_Init* Proc_Sweep_Init;
- Function_Sweep_Span* Proc_Sweep_Span;
- Function_Sweep_Span* Proc_Sweep_Drop;
- Function_Sweep_Step* Proc_Sweep_Step;
-
- Byte dropOutControl; /* current drop_out control method */
-
- Bool second_pass; /* indicates wether a horizontal pass */
- /* should be performed to control */
- /* drop-out accurately when calling */
- /* Render_Glyph. Note that there is */
- /* no horizontal pass during gray */
- /* rendering. */
- TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */
-
- TBand band_stack[16]; /* band stack used for sub-banding */
- Int band_top; /* band stack top */
-
- Int count_table[256]; /* Look-up table used to quickly count */
- /* set bits in a gray 2x2 cell */
-
- void* memory;
-
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- Byte grays[5]; /* Palette of gray levels used for */
- /* render. */
-
- Byte gray_lines[RASTER_GRAY_LINES];
- /* Intermediate table used to render the */
- /* graylevels pixmaps. */
- /* gray_lines is a buffer holding two */
- /* monochrome scanlines */
- Short gray_width; /* width in bytes of one monochrome */
- /* intermediate scanline of gray_lines. */
- /* Each gray pixel takes 2 bits long there */
-
- /* The gray_lines must hold 2 lines, thus with size */
- /* in bytes of at least `gray_width*2'. */
-
-#endif /* FT_RASTER_ANTI_ALIASING */
-
-#if 0
- PByte flags; /* current flags table */
- PUShort outs; /* current outlines table */
- FT_Vector* coords;
-
- UShort nPoints; /* number of points in current glyph */
- Short nContours; /* number of contours in current glyph */
-#endif
-
- };
-
-
-#ifdef FT_CONFIG_OPTION_STATIC_RASTER
-
- static TRaster_Instance cur_ras;
-#define ras cur_ras
-
-#else
-
-#define ras (*raster)
-
-#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
-
-
- /*************************************************************************/
- /*************************************************************************/
- /** **/
- /** PROFILES COMPUTATION **/
- /** **/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Set_High_Precision */
- /* */
- /* <Description> */
- /* Sets precision variables according to param flag. */
- /* */
- /* <Input> */
- /* High :: Set to True for high precision (typically for ppem < 18), */
- /* false otherwise. */
- /* */
- static
- void Set_High_Precision( RAS_ARGS Int High )
- {
- if ( High )
- {
- ras.precision_bits = 10;
- ras.precision_step = 128;
- ras.precision_jitter = 24;
- }
- else
- {
- ras.precision_bits = 6;
- ras.precision_step = 32;
- ras.precision_jitter = 2;
- }
-
- FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
-
- ras.precision = 1L << ras.precision_bits;
- ras.precision_half = ras.precision / 2;
- ras.precision_shift = ras.precision_bits - Pixel_Bits;
- ras.precision_mask = -ras.precision;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* New_Profile */
- /* */
- /* <Description> */
- /* Creates a new profile in the render pool. */
- /* */
- /* <Input> */
- /* aState :: The state/orientation of the new profile. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
- /* profile. */
- /* */
- static
- Bool New_Profile( RAS_ARGS TStates aState )
- {
- if ( !ras.fProfile )
- {
- ras.cProfile = (PProfile)ras.top;
- ras.fProfile = ras.cProfile;
- ras.top += AlignProfileSize;
- }
-
- if ( ras.top >= ras.maxBuff )
- {
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
-
- switch ( aState )
- {
- case Ascending:
- ras.cProfile->flow = Flow_Up;
- FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
- break;
-
- case Descending:
- ras.cProfile->flow = Flow_Down;
- FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
- break;
-
- default:
- FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
- ras.error = Raster_Err_Invalid;
- return FAILURE;
- }
-
- ras.cProfile->start = 0;
- ras.cProfile->height = 0;
- ras.cProfile->offset = ras.top;
- ras.cProfile->link = (PProfile)0;
- ras.cProfile->next = (PProfile)0;
-
- if ( !ras.gProfile )
- ras.gProfile = ras.cProfile;
-
- ras.state = aState;
- ras.fresh = TRUE;
- ras.joint = FALSE;
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* End_Profile */
- /* */
- /* <Description> */
- /* Finalizes the current profile. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
- /* */
- static
- Bool End_Profile( RAS_ARG )
- {
- Long h;
- PProfile oldProfile;
-
-
- h = ras.top - ras.cProfile->offset;
-
- if ( h < 0 )
- {
- FT_ERROR(( "End_Profile: negative height encountered!\n" ));
- ras.error = Raster_Err_Neg_Height;
- return FAILURE;
- }
-
- if ( h > 0 )
- {
- FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
- (long)ras.cProfile, ras.cProfile->start, h ));
-
- oldProfile = ras.cProfile;
- ras.cProfile->height = h;
- ras.cProfile = (PProfile)ras.top;
-
- ras.top += AlignProfileSize;
-
- ras.cProfile->height = 0;
- ras.cProfile->offset = ras.top;
- oldProfile->next = ras.cProfile;
- ras.num_Profs++;
- }
-
- if ( ras.top >= ras.maxBuff )
- {
- FT_TRACE1(( "overflow in End_Profile\n" ));
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
-
- ras.joint = FALSE;
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Insert_Y_Turn */
- /* */
- /* <Description> */
- /* Inserts a salient into the sorted list placed on top of the render */
- /* pool. */
- /* */
- /* <Input> */
- /* New y scanline position. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow. */
- /* */
- static
- Bool Insert_Y_Turn( RAS_ARGS Int y )
- {
- PLong y_turns;
- Int y2, n;
-
-
- n = ras.numTurns - 1;
- y_turns = ras.sizeBuff - ras.numTurns;
-
- /* look for first y value that is <= */
- while ( n >= 0 && y < y_turns[n] )
- n--;
-
- /* if it is <, simply insert it, ignore if == */
- if ( n >= 0 && y > y_turns[n] )
- while ( n >= 0 )
- {
- y2 = y_turns[n];
- y_turns[n] = y;
- y = y2;
- n--;
- }
-
- if ( n < 0 )
- {
- if ( ras.maxBuff <= ras.top )
- {
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
- ras.maxBuff--;
- ras.numTurns++;
- ras.sizeBuff[-ras.numTurns] = y;
- }
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Finalize_Profile_Table */
- /* */
- /* <Description> */
- /* Adjusts all links in the profiles list. */
- /* */
- /* <Return> */
- /* SUCCESS on success. FAILURE in case of overflow. */
- /* */
- static
- Bool Finalize_Profile_Table( RAS_ARG )
- {
- Int bottom, top;
- UShort n;
- PProfile p;
-
-
- n = ras.num_Profs;
-
- if ( n > 1 )
- {
- p = ras.fProfile;
- while ( n > 0 )
- {
- if ( n > 1 )
- p->link = (PProfile)( p->offset + p->height );
- else
- p->link = NULL;
-
- switch ( p->flow )
- {
- case Flow_Down:
- bottom = p->start - p->height+1;
- top = p->start;
- p->start = bottom;
- p->offset += p->height - 1;
- break;
-
- case Flow_Up:
- default:
- bottom = p->start;
- top = p->start + p->height - 1;
- }
-
- if ( Insert_Y_Turn( RAS_VARS bottom ) ||
- Insert_Y_Turn( RAS_VARS top + 1 ) )
- return FAILURE;
-
- p = p->link;
- n--;
- }
- }
- else
- ras.fProfile = NULL;
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Split_Conic */
- /* */
- /* <Description> */
- /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */
- /* stack. */
- /* */
- /* <Input> */
- /* None (subdivided Bezier is taken from the top of the stack). */
- /* */
- /* <Note> */
- /* This routine is the `beef' of this component. It is _the_ inner */
- /* loop that should be optimized to hell to get the best performance. */
- /* */
- static
- void Split_Conic( TPoint* base )
- {
- Long a, b;
-
-
- base[4].x = base[2].x;
- b = base[1].x;
- a = base[3].x = ( base[2].x + b ) / 2;
- b = base[1].x = ( base[0].x + b ) / 2;
- base[2].x = ( a + b ) / 2;
-
- base[4].y = base[2].y;
- b = base[1].y;
- a = base[3].y = ( base[2].y + b ) / 2;
- b = base[1].y = ( base[0].y + b ) / 2;
- base[2].y = ( a + b ) / 2;
-
- /* hand optimized. gcc doesn't seem too good at common expression */
- /* substitution and instruction scheduling ;-) */
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Split_Cubic */
- /* */
- /* <Description> */
- /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */
- /* Bezier stack. */
- /* */
- /* <Note> */
- /* This routine is the `beef' of the component. It is one of _the_ */
- /* inner loops that should be optimized like hell to get the best */
- /* performance. */
- /* */
- static
- void Split_Cubic( TPoint* base )
- {
- Long a, b, c, d;
-
-
- base[6].x = base[3].x;
- c = base[1].x;
- d = base[2].x;
- base[1].x = a = ( base[0].x + c + 1 ) >> 1;
- base[5].x = b = ( base[3].x + d + 1 ) >> 1;
- c = ( c + d + 1 ) >> 1;
- base[2].x = a = ( a + c + 1 ) >> 1;
- base[4].x = b = ( b + c + 1 ) >> 1;
- base[3].x = ( a + b + 1 ) >> 1;
-
- base[6].y = base[3].y;
- c = base[1].y;
- d = base[2].y;
- base[1].y = a = ( base[0].y + c + 1 ) >> 1;
- base[5].y = b = ( base[3].y + d + 1 ) >> 1;
- c = ( c + d + 1 ) >> 1;
- base[2].y = a = ( a + c + 1 ) >> 1;
- base[4].y = b = ( b + c + 1 ) >> 1;
- base[3].y = ( a + b + 1 ) >> 1;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_Up */
- /* */
- /* <Description> */
- /* Computes the x-coordinates of an ascending line segment and stores */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* x1 :: The x-coordinate of the segment's start point. */
- /* */
- /* y1 :: The y-coordinate of the segment's start point. */
- /* */
- /* x2 :: The x-coordinate of the segment's end point. */
- /* */
- /* y2 :: The y-coordinate of the segment's end point. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
- static
- Bool Line_Up( RAS_ARGS Long x1, Long y1,
- Long x2, Long y2,
- Long miny, Long maxy )
- {
- Long Dx, Dy;
- Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
- Long Ix, Rx, Ax;
-
- PLong top;
-
-
- Dx = x2 - x1;
- Dy = y2 - y1;
-
- if ( Dy <= 0 || y2 < miny || y1 > maxy )
- return SUCCESS;
-
- if ( y1 < miny )
- {
- /* Take care: miny-y1 can be a very large value; we use */
- /* a slow MulDiv function to avoid clipping bugs */
- x1 += SMulDiv( Dx, miny - y1, Dy );
- e1 = TRUNC( miny );
- f1 = 0;
- }
- else
- {
- e1 = TRUNC( y1 );
- f1 = FRAC( y1 );
- }
-
- if ( y2 > maxy )
- {
- /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
- e2 = TRUNC( maxy );
- f2 = 0;
- }
- else
- {
- e2 = TRUNC( y2 );
- f2 = FRAC( y2 );
- }
-
- if ( f1 > 0 )
- {
- if ( e1 == e2 )
- return SUCCESS;
- else
- {
- x1 += FMulDiv( Dx, ras.precision - f1, Dy );
- e1 += 1;
- }
- }
- else
- if ( ras.joint )
- {
- ras.top--;
- ras.joint = FALSE;
- }
-
- ras.joint = ( f2 == 0 );
-
- if ( ras.fresh )
- {
- ras.cProfile->start = e1;
- ras.fresh = FALSE;
- }
-
- size = e2 - e1 + 1;
- if ( ras.top + size >= ras.maxBuff )
- {
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
-
- if ( Dx > 0 )
- {
- Ix = ( ras.precision * Dx ) / Dy;
- Rx = ( ras.precision * Dx ) % Dy;
- Dx = 1;
- }
- else
- {
- Ix = -( ( ras.precision * -Dx ) / Dy );
- Rx = ( ras.precision * -Dx ) % Dy;
- Dx = -1;
- }
-
- Ax = -Dy;
- top = ras.top;
-
- while ( size > 0 )
- {
- *top++ = x1;
-
- x1 += Ix;
- Ax += Rx;
- if ( Ax >= 0 )
- {
- Ax -= Dy;
- x1 += Dx;
- }
- size--;
- }
-
- ras.top = top;
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_Down */
- /* */
- /* <Description> */
- /* Computes the x-coordinates of an descending line segment and */
- /* stores them in the render pool. */
- /* */
- /* <Input> */
- /* x1 :: The x-coordinate of the segment's start point. */
- /* */
- /* y1 :: The y-coordinate of the segment's start point. */
- /* */
- /* x2 :: The x-coordinate of the segment's end point. */
- /* */
- /* y2 :: The y-coordinate of the segment's end point. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
- static
- Bool Line_Down( RAS_ARGS Long x1, Long y1,
- Long x2, Long y2,
- Long miny, Long maxy )
- {
- Bool result, fresh;
-
-
- fresh = ras.fresh;
-
- result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
-
- if ( fresh && !ras.fresh )
- ras.cProfile->start = -ras.cProfile->start;
-
- return result;
- }
-
-
- /* A function type describing the functions used to split Bezier arcs */
- typedef void (*TSplitter)( TPoint* base );
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Bezier_Up */
- /* */
- /* <Description> */
- /* Computes the x-coordinates of an ascending Bezier arc and stores */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* degree :: The degree of the Bezier arc (either 2 or 3). */
- /* */
- /* splitter :: The function to split Bezier arcs. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
- static
- Bool Bezier_Up( RAS_ARGS Int degree,
- TSplitter splitter,
- Long miny,
- Long maxy )
- {
- Long y1, y2, e, e2, e0;
- Short f1;
-
- TPoint* arc;
- TPoint* start_arc;
-
- PLong top;
-
-
- arc = ras.arc;
- y1 = arc[degree].y;
- y2 = arc[0].y;
- top = ras.top;
-
- if ( y2 < miny || y1 > maxy )
- goto Fin;
-
- e2 = FLOOR( y2 );
-
- if ( e2 > maxy )
- e2 = maxy;
-
- e0 = miny;
-
- if ( y1 < miny )
- e = miny;
- else
- {
- e = CEILING( y1 );
- f1 = FRAC( y1 );
- e0 = e;
-
- if ( f1 == 0 )
- {
- if ( ras.joint )
- {
- top--;
- ras.joint = FALSE;
- }
-
- *top++ = arc[degree].x;
-
- e += ras.precision;
- }
- }
-
- if ( ras.fresh )
- {
- ras.cProfile->start = TRUNC( e0 );
- ras.fresh = FALSE;
- }
-
- if ( e2 < e )
- goto Fin;
-
- if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
- {
- ras.top = top;
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
-
- start_arc = arc;
-
- while ( arc >= start_arc && e <= e2 )
- {
- ras.joint = FALSE;
-
- y2 = arc[0].y;
-
- if ( y2 > e )
- {
- y1 = arc[degree].y;
- if ( y2 - y1 >= ras.precision_step )
- {
- splitter( arc );
- arc += degree;
- }
- else
- {
- *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
- e - y1, y2 - y1 );
- arc -= degree;
- e += ras.precision;
- }
- }
- else
- {
- if ( y2 == e )
- {
- ras.joint = TRUE;
- *top++ = arc[0].x;
-
- e += ras.precision;
- }
- arc -= degree;
- }
- }
-
- Fin:
- ras.top = top;
- ras.arc -= degree;
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Bezier_Down */
- /* */
- /* <Description> */
- /* Computes the x-coordinates of an descending Bezier arc and stores */
- /* them in the render pool. */
- /* */
- /* <Input> */
- /* degree :: The degree of the Bezier arc (either 2 or 3). */
- /* */
- /* splitter :: The function to split Bezier arcs. */
- /* */
- /* miny :: A lower vertical clipping bound value. */
- /* */
- /* maxy :: An upper vertical clipping bound value. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow. */
- /* */
- static
- Bool Bezier_Down( RAS_ARGS Int degree,
- TSplitter splitter,
- Long miny,
- Long maxy )
- {
- TPoint* arc = ras.arc;
- Bool result, fresh;
-
-
- arc[0].y = -arc[0].y;
- arc[1].y = -arc[1].y;
- arc[2].y = -arc[2].y;
- if ( degree > 2 )
- arc[3].y = -arc[3].y;
-
- fresh = ras.fresh;
-
- result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
-
- if ( fresh && !ras.fresh )
- ras.cProfile->start = -ras.cProfile->start;
-
- arc[0].y = -arc[0].y;
- return result;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Line_To */
- /* */
- /* <Description> */
- /* Injects a new line segment and adjusts Profiles list. */
- /* */
- /* <Input> */
- /* x :: The x-coordinate of the segment's end point (its start point */
- /* is stored in `LastX'). */
- /* */
- /* y :: The y-coordinate of the segment's end point (its start point */
- /* is stored in `LastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
- static
- Bool Line_To( RAS_ARGS Long x,
- Long y )
- {
- /* First, detect a change of direction */
-
- switch ( ras.state )
- {
- case Unknown:
- if ( y > ras.lastY )
- {
- if ( New_Profile( RAS_VARS Ascending ) )
- return FAILURE;
- }
- else
- {
- if ( y < ras.lastY )
- if ( New_Profile( RAS_VARS Descending ) )
- return FAILURE;
- }
- break;
-
- case Ascending:
- if ( y < ras.lastY )
- {
- if ( End_Profile( RAS_VAR ) ||
- New_Profile( RAS_VARS Descending ) )
- return FAILURE;
- }
- break;
-
- case Descending:
- if ( y > ras.lastY )
- {
- if ( End_Profile( RAS_VAR ) ||
- New_Profile( RAS_VARS Ascending ) )
- return FAILURE;
- }
- break;
-
- default:
- ;
- }
-
- /* Then compute the lines */
-
- switch ( ras.state )
- {
- case Ascending:
- if ( Line_Up ( RAS_VARS ras.lastX, ras.lastY,
- x, y, ras.minY, ras.maxY ) )
- return FAILURE;
- break;
-
- case Descending:
- if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
- x, y, ras.minY, ras.maxY ) )
- return FAILURE;
- break;
-
- default:
- ;
- }
-
- ras.lastX = x;
- ras.lastY = y;
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Conic_To */
- /* */
- /* <Description> */
- /* Injects a new conic arc and adjusts the profile list. */
- /* */
- /* <Input> */
- /* cx :: The x-coordinate of the arc's new control point. */
- /* */
- /* cy :: The y-coordinate of the arc's new control point. */
- /* */
- /* x :: The x-coordinate of the arc's end point (its start point is */
- /* stored in `LastX'). */
- /* */
- /* y :: The y-coordinate of the arc's end point (its start point is */
- /* stored in `LastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
- static
- Bool Conic_To( RAS_ARGS Long cx,
- Long cy,
- Long x,
- Long y )
- {
- Long y1, y2, y3, x3, ymin, ymax;
- TStates state_bez;
-
-
- ras.arc = ras.arcs;
- ras.arc[2].x = ras.lastX;
- ras.arc[2].y = ras.lastY;
- ras.arc[1].x = cx; ras.arc[1].y = cy;
- ras.arc[0].x = x; ras.arc[0].y = y;
-
- do
- {
- y1 = ras.arc[2].y;
- y2 = ras.arc[1].y;
- y3 = ras.arc[0].y;
- x3 = ras.arc[0].x;
-
- /* first, categorize the Bezier arc */
-
- if ( y1 <= y3 )
- {
- ymin = y1;
- ymax = y3;
- }
- else
- {
- ymin = y3;
- ymax = y1;
- }
-
- if ( y2 < ymin || y2 > ymax )
- {
- /* this arc has no given direction, split it! */
- Split_Conic( ras.arc );
- ras.arc += 2;
- }
- else if ( y1 == y3 )
- {
- /* this arc is flat, ignore it and pop it from the Bezier stack */
- ras.arc -= 2;
- }
- else
- {
- /* the arc is y-monotonous, either ascending or descending */
- /* detect a change of direction */
- state_bez = y1 < y3 ? Ascending : Descending;
- if ( ras.state != state_bez )
- {
- /* finalize current profile if any */
- if ( ras.state != Unknown &&
- End_Profile( RAS_VAR ) )
- goto Fail;
-
- /* create a new profile */
- if ( New_Profile( RAS_VARS state_bez ) )
- goto Fail;
- }
-
- /* now call the appropriate routine */
- if ( state_bez == Ascending )
- {
- if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
- goto Fail;
- }
- else
- if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
- goto Fail;
- }
-
- } while ( ras.arc >= ras.arcs );
-
- ras.lastX = x3;
- ras.lastY = y3;
-
- return SUCCESS;
-
- Fail:
- return FAILURE;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Cubic_To */
- /* */
- /* <Description> */
- /* Injects a new cubic arc and adjusts the profile list. */
- /* */
- /* <Input> */
- /* cx1 :: The x-coordinate of the arc's first new control point. */
- /* */
- /* cy1 :: The y-coordinate of the arc's first new control point. */
- /* */
- /* cx2 :: The x-coordinate of the arc's second new control point. */
- /* */
- /* cy2 :: The y-coordinate of the arc's second new control point. */
- /* */
- /* x :: The x-coordinate of the arc's end point (its start point is */
- /* stored in `LastX'). */
- /* */
- /* y :: The y-coordinate of the arc's end point (its start point is */
- /* stored in `LastY'). */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
- /* profile. */
- /* */
- static
- Bool Cubic_To( RAS_ARGS Long cx1,
- Long cy1,
- Long cx2,
- Long cy2,
- Long x,
- Long y )
- {
- Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
- TStates state_bez;
-
-
- ras.arc = ras.arcs;
- ras.arc[3].x = ras.lastX;
- ras.arc[3].y = ras.lastY;
- ras.arc[2].x = cx1; ras.arc[2].y = cy1;
- ras.arc[1].x = cx2; ras.arc[1].y = cy2;
- ras.arc[0].x = x; ras.arc[0].y = y;
-
- do
- {
- y1 = ras.arc[3].y;
- y2 = ras.arc[2].y;
- y3 = ras.arc[1].y;
- y4 = ras.arc[0].y;
- x4 = ras.arc[0].x;
-
- /* first, categorize the Bezier arc */
-
- if ( y1 <= y4 )
- {
- ymin1 = y1;
- ymax1 = y4;
- }
- else
- {
- ymin1 = y4;
- ymax1 = y1;
- }
-
- if ( y2 <= y3 )
- {
- ymin2 = y2;
- ymax2 = y3;
- }
- else
- {
- ymin2 = y3;
- ymax2 = y2;
- }
-
- if ( ymin2 < ymin1 || ymax2 > ymax1 )
- {
- /* this arc has no given direction, split it! */
- Split_Cubic( ras.arc );
- ras.arc += 3;
- }
- else if ( y1 == y4 )
- {
- /* this arc is flat, ignore it and pop it from the Bezier stack */
- ras.arc -= 3;
- }
- else
- {
- state_bez = y1 <= y4 ? Ascending : Descending;
-
- /* detect a change of direction */
- if ( ras.state != state_bez )
- {
- if ( ras.state != Unknown &&
- End_Profile( RAS_VAR ) )
- goto Fail;
-
- if ( New_Profile( RAS_VARS state_bez ) )
- goto Fail;
- }
-
- /* compute intersections */
- if ( state_bez == Ascending )
- {
- if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
- goto Fail;
- }
- else
- if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
- goto Fail;
- }
-
- } while ( ras.arc >= ras.arcs );
-
- ras.lastX = x4;
- ras.lastY = y4;
-
- return SUCCESS;
-
- Fail:
- return FAILURE;
- }
-
-
-#undef SWAP_
-#define SWAP_( x, y ) do \
- { \
- Long swap = x; \
- \
- \
- x = y; \
- y = swap; \
- } while ( 0 )
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Decompose_Curve */
- /* */
- /* <Description> */
- /* Scans the outline arays in order to emit individual segments and */
- /* Beziers by calling Line_To() and Bezier_To(). It handles all */
- /* weird cases, like when the first point is off the curve, or when */
- /* there are simply no `on' points in the contour! */
- /* */
- /* <Input> */
- /* first :: The index of the first point in the contour. */
- /* */
- /* last :: The index of the last point in the contour. */
- /* */
- /* flipped :: If set, flip the direction of the curve. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE on error. */
- /* */
- static
- Bool Decompose_Curve( RAS_ARGS UShort first,
- UShort last,
- int flipped )
- {
- FT_Vector v_last;
- FT_Vector v_control;
- FT_Vector v_start;
-
- FT_Vector* points;
- FT_Vector* point;
- FT_Vector* limit;
- char* tags;
-
- char tag; /* current point's state */
-
-
- points = ras.outline.points;
- limit = points + last;
-
- v_start.x = SCALED( points[first].x );
- v_start.y = SCALED( points[first].y );
- v_last.x = SCALED( points[last].x );
- v_last.y = SCALED( points[last].y );
-
- if ( flipped )
- {
- SWAP_( v_start.x, v_start.y );
- SWAP_( v_last.x, v_last.y );
- }
-
- v_control = v_start;
-
- point = points + first;
- tags = ras.outline.tags + first;
- tag = FT_CURVE_TAG( tags[0] );
-
- /* A contour cannot start with a cubic control point! */
- if ( tag == FT_Curve_Tag_Cubic )
- goto Invalid_Outline;
-
- /* check first point to determine origin */
- if ( tag == FT_Curve_Tag_Conic )
- {
- /* first point is conic control. Yes, this happens. */
- if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
- {
- /* start at last point if it is on the curve */
- v_start = v_last;
- limit--;
- }
- else
- {
- /* if both first and last points are conic, */
- /* start at their middle and record its position */
- /* for closure */
- v_start.x = ( v_start.x + v_last.x ) / 2;
- v_start.y = ( v_start.y + v_last.y ) / 2;
-
- v_last = v_start;
- }
- point--;
- tags--;
- }
-
- ras.lastX = v_start.x;
- ras.lastY = v_start.y;
-
- while ( point < limit )
- {
- point++;
- tags++;
-
- tag = FT_CURVE_TAG( tags[0] );
-
- switch ( tag )
- {
- case FT_Curve_Tag_On: /* emit a single line_to */
- {
- Long x, y;
-
-
- x = SCALED( point->x );
- y = SCALED( point->y );
- if ( flipped )
- SWAP_( x, y );
-
- if ( Line_To( RAS_VARS x, y ) )
- goto Fail;
- continue;
- }
-
- case FT_Curve_Tag_Conic: /* consume conic arcs */
- {
- v_control.x = SCALED( point[0].x );
- v_control.y = SCALED( point[0].y );
-
- if ( flipped )
- SWAP_( v_control.x, v_control.y );
-
- Do_Conic:
- if ( point < limit )
- {
- FT_Vector v_middle;
- Long x, y;
-
-
- point++;
- tags++;
- tag = FT_CURVE_TAG( tags[0] );
-
- x = SCALED( point[0].x );
- y = SCALED( point[0].y );
-
- if ( flipped )
- SWAP_( x, y );
-
- if ( tag == FT_Curve_Tag_On )
- {
- if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
- goto Fail;
- continue;
- }
-
- if ( tag != FT_Curve_Tag_Conic )
- goto Invalid_Outline;
-
- v_middle.x = ( v_control.x + x ) / 2;
- v_middle.y = ( v_control.y + y ) / 2;
-
- if ( Conic_To( RAS_VARS v_control.x, v_control.y,
- v_middle.x, v_middle.y ) )
- goto Fail;
-
- v_control.x = x;
- v_control.y = y;
-
- goto Do_Conic;
- }
-
- if ( Conic_To( RAS_VARS v_control.x, v_control.y,
- v_start.x, v_start.y ) )
- goto Fail;
-
- goto Close;
- }
-
- default: /* FT_Curve_Tag_Cubic */
- {
- Long x1, y1, x2, y2, x3, y3;
-
-
- if ( point + 1 > limit ||
- FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
- goto Invalid_Outline;
-
- point += 2;
- tags += 2;
-
- x1 = SCALED( point[-2].x );
- y1 = SCALED( point[-2].y );
- x2 = SCALED( point[-1].x );
- y2 = SCALED( point[-1].y );
- x3 = SCALED( point[ 0].x );
- y3 = SCALED( point[ 0].y );
-
- if ( flipped )
- {
- SWAP_( x1, y1 );
- SWAP_( x2, y2 );
- SWAP_( x3, y3 );
- }
-
- if ( point <= limit )
- {
- if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
- goto Fail;
- continue;
- }
-
- if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
- goto Fail;
- goto Close;
- }
- }
- }
-
- /* close the contour with a line segment */
- if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
- goto Fail;
-
- Close:
- return SUCCESS;
-
- Invalid_Outline:
- ras.error = Raster_Err_Invalid;
-
- Fail:
- return FAILURE;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Convert_Glyph */
- /* */
- /* <Description> */
- /* Converts a glyph into a series of segments and arcs and makes a */
- /* profiles list with them. */
- /* */
- /* <Input> */
- /* flipped :: If set, flip the direction of curve. */
- /* */
- /* <Return> */
- /* SUCCESS on success, FAILURE if any error was encountered during */
- /* rendering. */
- /* */
- static
- Bool Convert_Glyph( RAS_ARGS int flipped )
- {
- Short i;
- UShort start;
-
- PProfile lastProfile;
-
-
- ras.fProfile = NULL;
- ras.joint = FALSE;
- ras.fresh = FALSE;
-
- ras.maxBuff = ras.sizeBuff - AlignProfileSize;
-
- ras.numTurns = 0;
-
- ras.cProfile = (PProfile)ras.top;
- ras.cProfile->offset = ras.top;
- ras.num_Profs = 0;
-
- start = 0;
-
- for ( i = 0; i < ras.outline.n_contours; i++ )
- {
- ras.state = Unknown;
- ras.gProfile = NULL;
-
- if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) )
- return FAILURE;
-
- start = ras.outline.contours[i] + 1;
-
- /* We must now see whether the extreme arcs join or not */
- if ( FRAC( ras.lastY ) == 0 &&
- ras.lastY >= ras.minY &&
- ras.lastY <= ras.maxY )
- if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
- ras.top--;
- /* Note that ras.gProfile can be nil if the contour was too small */
- /* to be drawn. */
-
- lastProfile = ras.cProfile;
- if ( End_Profile( RAS_VAR ) )
- return FAILURE;
-
- /* close the `next profile in contour' linked list */
- if ( ras.gProfile )
- lastProfile->next = ras.gProfile;
- }
-
- if ( Finalize_Profile_Table( RAS_VAR ) )
- return FAILURE;
-
- return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
- }
-
-
- /*************************************************************************/
- /*************************************************************************/
- /** **/
- /** SCAN-LINE SWEEPS AND DRAWING **/
- /** **/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* Init_Linked */
- /* */
- /* Initializes an empty linked list. */
- /* */
- static
- void Init_Linked( TProfileList* l )
- {
- *l = NULL;
- }
-
-
- /*************************************************************************/
- /* */
- /* InsNew */
- /* */
- /* Inserts a new profile in a linked list. */
- /* */
- static
- void InsNew( PProfileList list,
- PProfile profile )
- {
- PProfile *old, current;
- Long x;
-
-
- old = list;
- current = *old;
- x = profile->X;
-
- while ( current )
- {
- if ( x < current->X )
- break;
- old = ¤t->link;
- current = *old;
- }
-
- profile->link = current;
- *old = profile;
- }
-
-
- /*************************************************************************/
- /* */
- /* DelOld */
- /* */
- /* Removes an old profile from a linked list. */
- /* */
- static
- void DelOld( PProfileList list,
- PProfile profile )
- {
- PProfile *old, current;
-
-
- old = list;
- current = *old;
-
- while ( current )
- {
- if ( current == profile )
- {
- *old = current->link;
- return;
- }
-
- old = ¤t->link;
- current = *old;
- }
-
- /* we should never get there, unless the profile was not part of */
- /* the list. */
- }
-
-
- /*************************************************************************/
- /* */
- /* Update */
- /* */
- /* Update all X offsets of a drawing list. */
- /* */
- static
- void Update( PProfile first )
- {
- PProfile current = first;
-
-
- while ( current )
- {
- current->X = *current->offset;
- current->offset += current->flow;
- current->height--;
- current = current->link;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* Sort */
- /* */
- /* Sorts a trace list. In 95%, the list is already sorted. We need */
- /* an algorithm which is fast in this case. Bubble sort is enough */
- /* and simple. */
- /* */
- static
- void Sort( PProfileList list )
- {
- PProfile *old, current, next;
-
-
- /* First, set the new X coordinate of each profile */
- Update( *list );
-
- /* Then sort them */
- old = list;
- current = *old;
-
- if ( !current )
- return;
-
- next = current->link;
-
- while ( next )
- {
- if ( current->X <= next->X )
- {
- old = ¤t->link;
- current = *old;
-
- if ( !current )
- return;
- }
- else
- {
- *old = next;
- current->link = next->link;
- next->link = current;
-
- old = list;
- current = *old;
- }
-
- next = current->link;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* Vertical Sweep Procedure Set */
- /* */
- /* These four routines are used during the vertical black/white */
- /* sweep phase by the generic Draw_Sweep() function. */
- /* */
- /*************************************************************************/
-
- static
- void Vertical_Sweep_Init( RAS_ARGS Short* min,
- Short* max )
- {
- Long pitch = ras.target.pitch;
-
- UNUSED( max );
-
-
- ras.traceIncr = (Short)-pitch;
- ras.traceOfs = -*min * pitch;
- if ( pitch > 0 )
- ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
-
- ras.gray_min_x = 0;
- ras.gray_max_x = 0;
- }
-
-
- static
- void Vertical_Sweep_Span( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- Short c1, c2;
- Byte f1, f2;
- Byte* target;
-
- UNUSED( y );
- UNUSED( left );
- UNUSED( right );
-
-
- /* Drop-out control */
-
- e1 = TRUNC( CEILING( x1 ) );
-
- if ( x2 - x1 - ras.precision <= ras.precision_jitter )
- e2 = e1;
- else
- e2 = TRUNC( FLOOR( x2 ) );
-
- if ( e2 >= 0 && e1 < ras.bWidth )
- {
- if ( e1 < 0 ) e1 = 0;
- if ( e2 >= ras.bWidth ) e2 = ras.bWidth - 1;
-
- c1 = (Short)( e1 >> 3 );
- c2 = (Short)( e2 >> 3 );
-
- f1 = (unsigned char)0xFF >> ( e1 & 7 );
- f2 = ~((unsigned char)0x7F >> ( e2 & 7 ));
-
- if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
- if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
-
- target = ras.bTarget + ras.traceOfs + c1;
- c2 -= c1;
-
- if ( c2 > 0 )
- {
- target[0] |= f1;
-
- /* memset() is slower than the following code on many platforms. */
- /* This is due to the fact that, in the vast majority of cases, */
- /* the span length in bytes is relatively small. */
- c2--;
- while ( c2 > 0 )
- {
- *(++target) = 0xFF;
- c2--;
- }
- target[1] |= f2;
- }
- else
- *target |= ( f1 & f2 );
- }
- }
-
-
- static
- void Vertical_Sweep_Drop( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- Short c1, f1;
-
-
- /* Drop-out control */
-
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
-
- if ( e1 > e2 )
- {
- if ( e1 == e2 + ras.precision )
- {
- switch ( ras.dropOutControl )
- {
- case 1:
- e1 = e2;
- break;
-
- case 4:
- e1 = CEILING( (x1 + x2 + 1) / 2 );
- break;
-
- case 2:
- case 5:
- /* Drop-out Control Rule #4 */
-
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
- /* */
- /* Here, we only get rid of stubs recognized if: */
- /* */
- /* upper stub: */
- /* */
- /* - P_Left and P_Right are in the same contour */
- /* - P_Right is the successor of P_Left in that contour */
- /* - y is the top of P_Left and P_Right */
- /* */
- /* lower stub: */
- /* */
- /* - P_Left and P_Right are in the same contour */
- /* - P_Left is the successor of P_Right in that contour */
- /* - y is the bottom of P_Left */
- /* */
-
- /* FIXXXME: uncommenting this line solves the disappearing */
- /* bit problem in the `7' of verdana 10pts, but */
- /* makes a new one in the `C' of arial 14pts */
-
-#if 0
- if ( x2 - x1 < ras.precision_half )
-#endif
- {
- /* upper stub test */
- if ( left->next == right && left->height <= 0 )
- return;
-
- /* lower stub test */
- if ( right->next == left && left->start == y )
- return;
- }
-
- /* check that the rightmost pixel isn't set */
-
- e1 = TRUNC( e1 );
-
- c1 = (Short)( e1 >> 3 );
- f1 = e1 & 7;
-
- if ( e1 >= 0 && e1 < ras.bWidth &&
- ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
- return;
-
- if ( ras.dropOutControl == 2 )
- e1 = e2;
- else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
-
- break;
-
- default:
- return; /* unsupported mode */
- }
- }
- else
- return;
- }
-
- e1 = TRUNC( e1 );
-
- if ( e1 >= 0 && e1 < ras.bWidth )
- {
- c1 = (Short)( e1 >> 3 );
- f1 = e1 & 7;
-
- if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
- if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
-
- ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
- }
- }
-
-
- static
- void Vertical_Sweep_Step( RAS_ARG )
- {
- ras.traceOfs += ras.traceIncr;
- }
-
-
- /***********************************************************************/
- /* */
- /* Horizontal Sweep Procedure Set */
- /* */
- /* These four routines are used during the horizontal black/white */
- /* sweep phase by the generic Draw_Sweep() function. */
- /* */
- /***********************************************************************/
-
- static
- void Horizontal_Sweep_Init( RAS_ARGS Short* min,
- Short* max )
- {
- /* nothing, really */
- UNUSED( raster );
- UNUSED( min );
- UNUSED( max );
- }
-
-
- static
- void Horizontal_Sweep_Span( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- PByte bits;
- Byte f1;
-
- UNUSED( left );
- UNUSED( right );
-
-
- if ( x2 - x1 < ras.precision )
- {
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
-
- if ( e1 == e2 )
- {
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
-
- e1 = TRUNC( e1 );
-
- if ( e1 >= 0 && e1 < ras.target.rows )
- {
- PByte p;
-
-
- p = bits - e1*ras.target.pitch;
- if ( ras.target.pitch > 0 )
- p += ( ras.target.rows - 1 ) * ras.target.pitch;
-
- p[0] |= f1;
- }
- }
- }
- }
-
-
- static
- void Horizontal_Sweep_Drop( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- PByte bits;
- Byte f1;
-
-
- /* During the horizontal sweep, we only take care of drop-outs */
-
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
-
- if ( e1 > e2 )
- {
- if ( e1 == e2 + ras.precision )
- {
- switch ( ras.dropOutControl )
- {
- case 1:
- e1 = e2;
- break;
-
- case 4:
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
- break;
-
- case 2:
- case 5:
-
- /* Drop-out Control Rule #4 */
-
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
- /* */
-
- /* rightmost stub test */
- if ( left->next == right && left->height <= 0 )
- return;
-
- /* leftmost stub test */
- if ( right->next == left && left->start == y )
- return;
-
- /* check that the rightmost pixel isn't set */
-
- e1 = TRUNC( e1 );
-
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
-
- bits -= e1 * ras.target.pitch;
- if ( ras.target.pitch > 0 )
- bits += ( ras.target.rows - 1 ) * ras.target.pitch;
-
- if ( e1 >= 0 &&
- e1 < ras.target.rows &&
- *bits & f1 )
- return;
-
- if ( ras.dropOutControl == 2 )
- e1 = e2;
- else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
-
- break;
-
- default:
- return; /* unsupported mode */
- }
- }
- else
- return;
- }
-
- bits = ras.bTarget + ( y >> 3 );
- f1 = (Byte)( 0x80 >> ( y & 7 ) );
-
- e1 = TRUNC( e1 );
-
- if ( e1 >= 0 && e1 < ras.target.rows )
- {
- bits -= e1 * ras.target.pitch;
- if ( ras.target.pitch > 0 )
- bits += ( ras.target.rows - 1 ) * ras.target.pitch;
-
- bits[0] |= f1;
- }
- }
-
-
- static
- void Horizontal_Sweep_Step( RAS_ARG )
- {
- /* Nothing, really */
- UNUSED( raster );
- }
-
-
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-
- /*************************************************************************/
- /* */
- /* Vertical Gray Sweep Procedure Set */
- /* */
- /* These two routines are used during the vertical gray-levels sweep */
- /* phase by the generic Draw_Sweep() function. */
- /* */
- /* NOTES */
- /* */
- /* - The target pixmap's width *must* be a multiple of 4. */
- /* */
- /* - You have to use the function Vertical_Sweep_Span() for the gray */
- /* span call. */
- /* */
- /*************************************************************************/
-
- static
- void Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
- Short* max )
- {
- Long pitch, byte_len;
-
-
- *min = *min & -2;
- *max = ( *max + 3 ) & -2;
-
- ras.traceOfs = 0;
- pitch = ras.target.pitch;
- byte_len = -pitch;
- ras.traceIncr = (Short)byte_len;
- ras.traceG = ( *min / 2 ) * byte_len;
-
- if ( pitch > 0 )
- {
- ras.traceG += ( ras.target.rows - 1 ) * pitch;
- byte_len = -byte_len;
- }
-
- ras.gray_min_x = (Short)byte_len;
- ras.gray_max_x = -(Short)byte_len;
- }
-
-
- static
- void Vertical_Gray_Sweep_Step( RAS_ARG )
- {
- Int c1, c2;
- PByte pix, bit, bit2;
- Int* count = ras.count_table;
- Byte* grays;
-
-
- ras.traceOfs += ras.gray_width;
-
- if ( ras.traceOfs > ras.gray_width )
- {
- pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
- grays = ras.grays;
-
- if ( ras.gray_max_x >= 0 )
- {
- Long last_pixel = ras.target.width - 1;
- Int last_cell = last_pixel >> 2;
- Int last_bit = last_pixel & 3;
- Bool over = 0;
-
- if ( ras.gray_max_x >= last_cell && last_bit != 3 )
- {
- ras.gray_max_x = last_cell - 1;
- over = 1;
- }
-
- if ( ras.gray_min_x < 0 )
- ras.gray_min_x = 0;
-
- bit = ras.bTarget + ras.gray_min_x;
- bit2 = bit + ras.gray_width;
-
- c1 = ras.gray_max_x - ras.gray_min_x;
-
- while ( c1 >= 0 )
- {
- c2 = count[*bit] + count[*bit2];
-
- if ( c2 )
- {
- pix[0] = grays[(c2 >> 12) & 0x000F];
- pix[1] = grays[(c2 >> 8 ) & 0x000F];
- pix[2] = grays[(c2 >> 4 ) & 0x000F];
- pix[3] = grays[ c2 & 0x000F];
-
- *bit = 0;
- *bit2 = 0;
- }
-
- bit++;
- bit2++;
- pix += 4;
- c1--;
- }
-
- if ( over )
- {
- c2 = count[*bit] + count[*bit2];
- if ( c2 )
- {
- switch ( last_bit )
- {
- case 2:
- pix[2] = grays[(c2 >> 4 ) & 0x000F];
- case 1:
- pix[1] = grays[(c2 >> 8 ) & 0x000F];
- default:
- pix[0] = grays[(c2 >> 12) & 0x000F];
- }
-
- *bit = 0;
- *bit2 = 0;
- }
- }
- }
-
- ras.traceOfs = 0;
- ras.traceG += ras.traceIncr;
-
- ras.gray_min_x = 32000;
- ras.gray_max_x = -32000;
- }
- }
-
-
- static
- void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- /* nothing, really */
- UNUSED( raster );
- UNUSED( y );
- UNUSED( x1 );
- UNUSED( x2 );
- UNUSED( left );
- UNUSED( right );
- }
-
-
- static
- void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
- FT_F26Dot6 x1,
- FT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- PByte pixel;
- Byte color;
-
-
- /* During the horizontal sweep, we only take care of drop-outs */
- e1 = CEILING( x1 );
- e2 = FLOOR ( x2 );
-
- if ( e1 > e2 )
- {
- if ( e1 == e2 + ras.precision )
- {
- switch ( ras.dropOutControl )
- {
- case 1:
- e1 = e2;
- break;
-
- case 4:
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
- break;
-
- case 2:
- case 5:
-
- /* Drop-out Control Rule #4 */
-
- /* The spec is not very clear regarding rule #4. It */
- /* presents a method that is way too costly to implement */
- /* while the general idea seems to get rid of `stubs'. */
- /* */
-
- /* rightmost stub test */
- if ( left->next == right && left->height <= 0 )
- return;
-
- /* leftmost stub test */
- if ( right->next == left && left->start == y )
- return;
-
- if ( ras.dropOutControl == 2 )
- e1 = e2;
- else
- e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
-
- break;
-
- default:
- return; /* unsupported mode */
- }
- }
- else
- return;
- }
-
- if ( e1 >= 0 )
- {
- if ( x2 - x1 >= ras.precision_half )
- color = ras.grays[2];
- else
- color = ras.grays[1];
-
- e1 = TRUNC( e1 ) / 2;
- if ( e1 < ras.target.rows )
- {
- pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
- if ( ras.target.pitch > 0 )
- pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
-
- if ( pixel[0] == ras.grays[0] )
- pixel[0] = color;
- }
- }
- }
-
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
- /*************************************************************************/
- /* */
- /* Generic Sweep Drawing routine */
- /* */
- /*************************************************************************/
-
- static
- Bool Draw_Sweep( RAS_ARG )
- {
- Short y, y_change, y_height;
-
- PProfile P, Q, P_Left, P_Right;
-
- Short min_Y, max_Y, top, bottom, dropouts;
-
- Long x1, x2, xs, e1, e2;
-
- TProfileList wait;
- TProfileList draw_left, draw_right;
-
-
- /* Init empty linked lists */
-
- Init_Linked( &wait );
-
- Init_Linked( &draw_left );
- Init_Linked( &draw_right );
-
- /* first, compute min and max Y */
-
- P = ras.fProfile;
- max_Y = (short)TRUNC( ras.minY );
- min_Y = (short)TRUNC( ras.maxY );
-
- while ( P )
- {
- Q = P->link;
-
- bottom = (Short)P->start;
- top = (Short)P->start + P->height - 1;
-
- if ( min_Y > bottom ) min_Y = bottom;
- if ( max_Y < top ) max_Y = top;
-
- P->X = 0;
- InsNew( &wait, P );
-
- P = Q;
- }
-
- /* Check the Y-turns */
- if ( ras.numTurns == 0 )
- {
- ras.error = Raster_Err_Invalid;
- return FAILURE;
- }
-
- /* Now inits the sweep */
-
- ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
-
- /* Then compute the distance of each profile from min_Y */
-
- P = wait;
-
- while ( P )
- {
- P->countL = P->start - min_Y;
- P = P->link;
- }
-
- /* Let's go */
-
- y = min_Y;
- y_height = 0;
-
- if ( ras.numTurns > 0 &&
- ras.sizeBuff[-ras.numTurns] == min_Y )
- ras.numTurns--;
-
- while ( ras.numTurns > 0 )
- {
- /* look in the wait list for new activations */
-
- P = wait;
-
- while ( P )
- {
- Q = P->link;
- P->countL -= y_height;
- if ( P->countL == 0 )
- {
- DelOld( &wait, P );
-
- switch ( P->flow )
- {
- case Flow_Up:
- InsNew( &draw_left, P );
- break;
-
- case Flow_Down:
- InsNew( &draw_right, P );
- break;
- }
- }
-
- P = Q;
- }
-
- /* Sort the drawing lists */
-
- Sort( &draw_left );
- Sort( &draw_right );
-
- y_change = (Short)ras.sizeBuff[-ras.numTurns--];
- y_height = y_change - y;
-
- while ( y < y_change )
- {
- /* Let's trace */
-
- dropouts = 0;
-
- P_Left = draw_left;
- P_Right = draw_right;
-
- while ( P_Left )
- {
- x1 = P_Left ->X;
- x2 = P_Right->X;
-
- if ( x1 > x2 )
- {
- xs = x1;
- x1 = x2;
- x2 = xs;
- }
-
- if ( x2 - x1 <= ras.precision )
- {
- e1 = FLOOR( x1 );
- e2 = CEILING( x2 );
-
- if ( ras.dropOutControl != 0 &&
- ( e1 > e2 || e2 == e1 + ras.precision ) )
- {
- /* a drop out was detected */
-
- P_Left ->X = x1;
- P_Right->X = x2;
-
- /* mark profile for drop-out processing */
- P_Left->countL = 1;
- dropouts++;
-
- goto Skip_To_Next;
- }
- }
-
- ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
-
- Skip_To_Next:
-
- P_Left = P_Left->link;
- P_Right = P_Right->link;
- }
-
- /* now perform the dropouts _after_ the span drawing */
- /* drop-outs processing has been moved out of the loop */
- /* for performance tuning */
- if ( dropouts > 0 )
- goto Scan_DropOuts;
-
- Next_Line:
-
- ras.Proc_Sweep_Step( RAS_VAR );
-
- y++;
-
- if ( y < y_change )
- {
- Sort( &draw_left );
- Sort( &draw_right );
- }
- }
-
- /* Now finalize the profiles that needs it */
-
- {
- PProfile Q, P;
-
-
- P = draw_left;
- while ( P )
- {
- Q = P->link;
- if ( P->height == 0 )
- DelOld( &draw_left, P );
- P = Q;
- }
- }
-
- {
- PProfile Q, P = draw_right;
-
-
- while ( P )
- {
- Q = P->link;
- if ( P->height == 0 )
- DelOld( &draw_right, P );
- P = Q;
- }
- }
- }
-
- /* for gray-scaling, flushes the bitmap scanline cache */
- while ( y <= max_Y )
- {
- ras.Proc_Sweep_Step( RAS_VAR );
- y++;
- }
-
- return SUCCESS;
-
- Scan_DropOuts:
-
- P_Left = draw_left;
- P_Right = draw_right;
-
- while ( P_Left )
- {
- if ( P_Left->countL )
- {
- P_Left->countL = 0;
-#if 0
- dropouts--; /* -- this is useful when debugging only */
-#endif
- ras.Proc_Sweep_Drop( RAS_VARS y,
- P_Left->X,
- P_Right->X,
- P_Left,
- P_Right );
- }
-
- P_Left = P_Left->link;
- P_Right = P_Right->link;
- }
-
- goto Next_Line;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Single_Pass */
- /* */
- /* <Description> */
- /* Performs one sweep with sub-banding. */
- /* */
- /* <Input> */
- /* flipped :: If set, flip the direction of the outline. */
- /* */
- /* <Return> */
- /* Renderer error code. */
- /* */
- static
- int Render_Single_Pass( RAS_ARGS Bool flipped )
- {
- Short i, j, k;
-
-
- while ( ras.band_top >= 0 )
- {
- ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
- ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
-
- ras.top = ras.buff;
-
- ras.error = Raster_Err_None;
-
- if ( Convert_Glyph( RAS_VARS flipped ) )
- {
- if ( ras.error != Raster_Err_Overflow )
- return FAILURE;
-
- ras.error = Raster_Err_None;
-
- /* sub-banding */
-
-#ifdef DEBUG_RASTER
- ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
-#endif
-
- i = ras.band_stack[ras.band_top].y_min;
- j = ras.band_stack[ras.band_top].y_max;
-
- k = ( i + j ) / 2;
-
- if ( ras.band_top >= 7 || k < i )
- {
- ras.band_top = 0;
- ras.error = Raster_Err_Invalid;
-
- return ras.error;
- }
-
- ras.band_stack[ras.band_top + 1].y_min = k;
- ras.band_stack[ras.band_top + 1].y_max = j;
-
- ras.band_stack[ras.band_top].y_max = k - 1;
-
- ras.band_top++;
- }
- else
- {
- if ( ras.fProfile )
- if ( Draw_Sweep( RAS_VAR ) )
- return ras.error;
- ras.band_top--;
- }
- }
-
- return SUCCESS;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Glyph */
- /* */
- /* <Description> */
- /* Renders a glyph in a bitmap. Sub-banding if needed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */
- /* */
- LOCAL_FUNC
- FT_Error Render_Glyph( RAS_ARG )
- {
- FT_Error error;
-
-
- Set_High_Precision( RAS_VARS ras.outline.flags &
- ft_outline_high_precision );
- ras.scale_shift = ras.precision_shift;
- ras.dropOutControl = 2;
- ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
-
- /* Vertical Sweep */
- ras.Proc_Sweep_Init = Vertical_Sweep_Init;
- ras.Proc_Sweep_Span = Vertical_Sweep_Span;
- ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
- ras.Proc_Sweep_Step = Vertical_Sweep_Step;
-
- ras.band_top = 0;
- ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = ras.target.rows - 1;
-
- ras.bWidth = ras.target.width;
- ras.bTarget = (Byte*)ras.target.buffer;
-
- if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
- return error;
-
- /* Horizontal Sweep */
- if ( ras.second_pass && ras.dropOutControl != 0 )
- {
- ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
- ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
- ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
- ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
-
- ras.band_top = 0;
- ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = ras.target.width - 1;
-
- if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
- return error;
- }
-
- return FT_Err_Ok;
- }
-
-
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Render_Gray_Glyph */
- /* */
- /* <Description> */
- /* Renders a glyph with grayscaling. Sub-banding if needed. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error Render_Gray_Glyph( RAS_ARG )
- {
- Long pixel_width;
- FT_Error error;
-
-
- Set_High_Precision( RAS_VARS ras.outline.flags &
- ft_outline_high_precision );
- ras.scale_shift = ras.precision_shift + 1;
- ras.dropOutControl = 2;
- ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
-
-
- /* Vertical Sweep */
-
- ras.band_top = 0;
- ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
-
- ras.bWidth = ras.gray_width;
- pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
-
- if ( ras.bWidth > pixel_width )
- ras.bWidth = pixel_width;
-
- ras.bWidth = ras.bWidth * 8;
- ras.bTarget = (Byte*)ras.gray_lines;
- ras.gTarget = (Byte*)ras.target.buffer;
-
- ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
- ras.Proc_Sweep_Span = Vertical_Sweep_Span;
- ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
- ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
-
- error = Render_Single_Pass( RAS_VARS 0 );
- if (error)
- return error;
-
- /* Horizontal Sweep */
- if ( ras.second_pass && ras.dropOutControl != 0 )
- {
- ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
- ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
- ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
- ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
-
- ras.band_top = 0;
- ras.band_stack[0].y_min = 0;
- ras.band_stack[0].y_max = ras.target.width * 2 - 1;
-
- error = Render_Single_Pass( RAS_VARS 1 );
- if (error)
- return error;
- }
-
- return FT_Err_Ok;
- }
-
-#else /* FT_RASTER_OPTION_ANTI_ALIASING */
-
- LOCAL_FUNC
- FT_Error Render_Gray_Glyph( RAS_ARG )
- {
- UNUSED_RASTER;
- return Raster_Err_Unsupported;
- }
-
-#endif
-
-
- static
- void ft_black_init( TRaster_Instance* raster )
- {
- FT_UInt n;
- FT_ULong c;
-
- /* setup count table */
- for ( n = 0; n < 256; n++ )
- {
- c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
-
- c = ( ( c << 6 ) & 0x3000 ) |
- ( ( c << 4 ) & 0x0300 ) |
- ( ( c << 2 ) & 0x0030 ) |
- (c & 0x0003 );
-
- raster->count_table[n] = c;
- }
-
- /* set default 5-levels gray palette */
- for ( n = 0; n < 5; n++ )
- raster->grays[n] = n * 255 / 4;
-
- raster->gray_width = RASTER_GRAY_LINES / 2;
- }
-
- /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
- /**** a static object. *****/
-
-#ifdef _STANDALONE_
-
-
- static
- int ft_black_new( void* memory,
- FT_Raster *araster )
- {
- static FT_RasterRec_ the_raster;
-
-
- *araster = &the_raster;
- memset( &the_raster, sizeof ( the_raster ), 0 );
- ft_black_init( &the_raster );
-
- return 0;
- }
-
-
- static
- void ft_black_done( FT_Raster raster )
- {
- /* nothing */
- raster->init = 0;
- }
-
-
-#else /* _STANDALONE_ */
-
-
- static
- int ft_black_new( FT_Memory memory,
- TRaster_Instance** araster )
- {
- FT_Error error;
- TRaster_Instance* raster;
-
-
- *araster = 0;
- if ( !ALLOC( raster, sizeof ( *raster ) ) )
- {
- raster->memory = memory;
- ft_black_init( raster );
-
- *araster = raster;
- }
-
- return error;
- }
-
-
- static
- void ft_black_done( TRaster_Instance* raster )
- {
- FT_Memory memory = (FT_Memory)raster->memory;
- FREE( raster );
- }
-
-
-#endif /* _STANDALONE_ */
-
-
- static
- void ft_black_reset( TRaster_Instance* raster,
- const char* pool_base,
- long pool_size )
- {
- if ( raster && pool_base && pool_size >= 4096 )
- {
- /* save the pool */
- raster->buff = (PLong)pool_base;
- raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
- }
- }
-
-
- static
- void ft_black_set_mode( TRaster_Instance* raster,
- unsigned long mode,
- const char* palette )
- {
- if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
- {
- /* set 5-levels gray palette */
- raster->grays[0] = palette[0];
- raster->grays[1] = palette[1];
- raster->grays[2] = palette[2];
- raster->grays[3] = palette[3];
- raster->grays[4] = palette[4];
- }
- }
-
-
- static
- int ft_black_render( TRaster_Instance* raster,
- FT_Raster_Params* params )
- {
- FT_Outline* outline = (FT_Outline*)params->source;
- FT_Bitmap* target_map = params->target;
-
-
- if ( !raster || !raster->buff || !raster->sizeBuff )
- return Raster_Err_Not_Ini;
-
- if ( !outline || !outline->contours || !outline->points )
- return Raster_Err_Invalid;
-
- /* return immediately if the outline is empty */
- if ( outline->n_points == 0 || outline->n_contours <= 0 )
- return Raster_Err_None;
-
- if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
- return Raster_Err_Invalid;
-
- if ( !target_map || !target_map->buffer )
- return Raster_Err_Invalid;
-
- /* this version of the raster does not support direct rendering, sorry */
- if ( params->flags & ft_raster_flag_direct )
- return Raster_Err_Unsupported;
-
- ras.outline = *outline;
- ras.target = *target_map;
-
- return ( params->flags & ft_raster_flag_aa
- ? Render_Gray_Glyph( raster )
- : Render_Glyph( raster ) );
- }
-
-
- FT_Raster_Funcs ft_default_raster =
- {
- ft_glyph_format_outline,
- (FT_Raster_New_Func) ft_black_new,
- (FT_Raster_Reset_Func) ft_black_reset,
- (FT_Raster_Set_Mode_Func)ft_black_set_mode,
- (FT_Raster_Render_Func) ft_black_render,
- (FT_Raster_Done_Func) ft_black_done
- };
-
-
-/* END */
--- a/src/base/rules.mk
+++ b/src/base/rules.mk
@@ -45,10 +45,8 @@
# object. It will then be linked to the final executable only if one of its
# symbols is used by the application.
#
-BASE_EXT_SRC := $(BASE_)ftraster.c \
- $(BASE_)ftglyph.c \
- $(BASE_)ftmm.c \
- $(BASE_)ftgrays.c
+BASE_EXT_SRC := $(BASE_)ftglyph.c \
+ $(BASE_)ftmm.c
# Default extensions objects
#
--- a/src/cff/module.mk
+++ b/src/cff/module.mk
@@ -1,7 +1,7 @@
make_module_list: add_cff_driver
add_cff_driver:
- $(OPEN_DRIVER)cff_driver_interface$(CLOSE_DRIVER)
+ $(OPEN_DRIVER)cff_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)cff $(ECHO_DRIVER_DESC)OpenType fonts with extension *.otf$(ECHO_DRIVER_DONE)
# EOF
--- a/src/cff/t2driver.c
+++ b/src/cff/t2driver.c
@@ -78,7 +78,7 @@
/* formats. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only horizontal layouts (left-to-right & right-to-left) are */
@@ -144,118 +144,10 @@
#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. */
- /* */
- /* horz_resolution :: The horizontal resolution of the output device. */
- /* */
- /* vert_resolution :: The vertical resolution of the output device. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static
- FT_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 whether 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 = (FT_UShort)( dim_x >> 6 );
- metrics->y_ppem = (FT_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> */
@@ -277,7 +169,7 @@
/* whether to hint the outline, etc). */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Load_Glyph( T2_GlyphSlot slot,
@@ -385,58 +277,57 @@
static
- FTDriver_Interface t2_get_interface( T2_Driver driver,
- const char* interface )
+ FT_Module_Interface t2_get_interface( T2_Driver driver,
+ const char* interface )
{
- FT_Driver sfntd = FT_Get_Driver( driver->root.library, "sfnt" );
- SFNT_Interface* sfnt;
+ FT_Module 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;
+ /* we simply pass our request to the "sfnt" module */
+ sfnt = FT_Get_Module( driver->root.root.library, "sfnt" );
+ return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0;
}
/* The FT_DriverInterface structure is defined in ftdriver.h. */
- const FT_DriverInterface cff_driver_interface =
+ const FT_Driver_Class cff_driver_class =
{
- sizeof ( T2_DriverRec ),
- sizeof ( TT_FaceRec ),
- sizeof ( FT_SizeRec ),
- sizeof ( T2_GlyphSlotRec ),
+ /* begin with the FT_Module_Class fields */
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( T2_DriverRec ),
+ "cff",
+ 0x10000,
+ 0x20000,
- "cff", /* driver name */
- 100, /* driver version == 1.0 */
- 200, /* driver requires FreeType 2.0 or above */
+ 0, /* module-specific interface */
+
+ (FT_Module_Constructor) T2_Init_Driver,
+ (FT_Module_Destructor) T2_Done_Driver,
+ (FT_Module_Requester) t2_get_interface,
+ },
+
+ /* now the specific driver fields */
+ sizeof( TT_FaceRec ),
+ sizeof( FT_SizeRec ),
+ sizeof( T2_GlyphSlotRec ),
- (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) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
- (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_setCharSizes) 0,
+ (FTDriver_setPixelSizes) 0,
+
(FTDriver_loadGlyph) Load_Glyph,
-
(FTDriver_getCharIndex) Get_Char_Index,
+
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
};
@@ -446,7 +337,7 @@
/*************************************************************************/
/* */
/* <Function> */
- /* getDriverInterface */
+ /* getDriverClass */
/* */
/* <Description> */
/* This function is used when compiling the TrueType driver as a */
@@ -462,9 +353,9 @@
/* format-specific interface can then be retrieved through the method */
/* interface->get_format_interface. */
/* */
- EXPORT_FUNC( FT_DriverInterface* ) getDriverInterface( void )
+ EXPORT_FUNC( FT_Driver_Class* ) getDriverClass( void )
{
- return &cff_driver_interface;
+ return &cff_driver_class;
}
--- a/src/cff/t2driver.h
+++ b/src/cff/t2driver.h
@@ -19,12 +19,9 @@
#ifndef T2DRIVER_H
#define T2DRIVER_H
-#include <freetype/freetype.h>
#include <freetype/internal/ftdriver.h>
-#include <t2objs.h>
-
- FT_EXPORT_VAR( const FT_DriverInterface ) cff_driver_interface;
+ FT_EXPORT_VAR( const FT_Driver_Class ) cff_driver_class;
#endif /* T2DRIVER_H */
--- a/src/cff/t2gload.c
+++ b/src/cff/t2gload.c
@@ -231,9 +231,12 @@
if ( glyph )
{
- builder->base = glyph->root.outline;
- builder->max_points = glyph->max_points;
- builder->max_contours = glyph->max_contours;
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+ FT_GlyphLoader_Rewind( loader );
}
if ( size )
@@ -249,10 +252,6 @@
builder->left_bearing.y = 0;
builder->advance.x = 0;
builder->advance.y = 0;
-
- builder->base.n_points = 0;
- builder->base.n_contours = 0;
- builder->current = builder->base;
}
@@ -274,13 +273,8 @@
{
T2_GlyphSlot glyph = builder->glyph;
-
if ( glyph )
- {
- glyph->root.outline = builder->base;
- glyph->max_points = builder->max_points;
- glyph->max_contours = builder->max_contours;
- }
+ glyph->root.outline = *builder->base;
}
@@ -366,45 +360,11 @@
FT_Error check_points( T2_Builder* builder,
FT_Int count )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
+ return FT_GlyphLoader_Check_Points( builder->loader,
+ count, 0 );
+ }
- if ( !builder->load_points )
- return T2_Err_Ok;
-
- count += base->n_points + outline->n_points;
-
- /* realloc points table if necessary */
- if ( count >= builder->max_points )
- {
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->points - base->points;
- FT_Int current = builder->max_points;
-
-
- while ( builder->max_points < count )
- builder->max_points += 8;
-
- if ( REALLOC_ARRAY( base->points, current,
- builder->max_points, FT_Vector ) ||
-
- REALLOC_ARRAY( base->tags, current,
- builder->max_points, FT_Byte ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->points = base->points + increment;
- outline->tags = base->tags + increment;
- }
-
- return T2_Err_Ok;
- }
-
-
/* add a new point, do not check space */
static
void add_point( T2_Builder* builder,
@@ -412,15 +372,13 @@
FT_Pos y,
FT_Byte flag )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
-
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
-
point->x = x >> 16;
point->y = y >> 16;
*control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
@@ -427,7 +385,6 @@
builder->last = *point;
}
-
outline->n_points++;
}
@@ -440,7 +397,6 @@
{
FT_Error error;
-
error = check_points( builder, 1 );
if ( !error )
add_point( builder, x, y, 1 );
@@ -453,10 +409,9 @@
static
FT_Error add_contour( T2_Builder* builder )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
+ FT_Error error;
-
if ( !builder->load_points )
{
outline->n_contours++;
@@ -463,34 +418,15 @@
return T2_Err_Ok;
}
- /* realloc contours array if necessary */
- if ( base->n_contours + outline->n_contours >= builder->max_contours &&
- builder->load_points )
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if (!error)
{
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->contours - base->contours;
- FT_Int current = builder->max_contours;
-
-
- builder->max_contours += 4;
-
- if ( REALLOC_ARRAY( base->contours,
- current, builder->max_contours, FT_Short ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->contours = base->contours + increment;
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+ outline->n_contours++;
}
-
- if ( outline->n_contours > 0 )
- outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-
- outline->n_contours++;
-
- return T2_Err_Ok;
+ return error;
}
@@ -505,7 +441,6 @@
{
FT_Error error;
-
builder->path_begun = 1;
error = add_contour( builder );
if ( error )
@@ -520,9 +455,8 @@
static
void close_contour( T2_Builder* builder )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
-
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
@@ -550,7 +484,7 @@
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error T2_Parse_CharStrings( T2_Decoder* decoder,
@@ -593,7 +527,7 @@
ip = zone->cursor = zone->base;
error = T2_Err_Ok;
- outline = &builder->current;
+ outline = builder->current;
x = builder->pos_x;
y = builder->pos_y;
@@ -1182,8 +1116,7 @@
close_contour( builder );
/* add current outline to the glyph slot */
- builder->base.n_points += builder->current.n_points;
- builder->base.n_contours += builder->current.n_contours;
+ FT_GlyphLoader_Add( builder->loader );
/* return now! */
FT_TRACE4(( "\n\n" ));
@@ -1769,7 +1702,7 @@
{
/* scale the outline and the metrics */
FT_Int n;
- FT_Outline* cur = &decoder.builder.base;
+ FT_Outline* cur = &glyph->root.outline;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
--- a/src/cff/t2gload.h
+++ b/src/cff/t2gload.h
@@ -85,34 +85,31 @@
/* */
typedef struct T2_Builder_
{
- FT_Memory memory;
- TT_Face face;
- T2_GlyphSlot glyph;
+ FT_Memory memory;
+ TT_Face face;
+ T2_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+ FT_Outline* base;
+ FT_Outline* current;
- FT_Outline current; /* the current glyph outline */
- FT_Outline base; /* the composite glyph outline */
+ FT_Vector last;
- FT_Int max_points; /* capacity of base outline in points */
- FT_Int max_contours; /* capacity of base outline in contours */
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
- FT_Vector last;
+ FT_Pos pos_x;
+ FT_Pos pos_y;
- FT_Fixed scale_x;
- FT_Fixed scale_y;
+ FT_Vector left_bearing;
+ FT_Vector advance;
- FT_Pos pos_x;
- FT_Pos pos_y;
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
- FT_Vector left_bearing;
- FT_Vector advance;
-
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
- FT_Bool no_recurse;
-
- FT_Error error; /* only used for memory errors */
- FT_Bool metrics_only;
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
} T2_Builder;
--- a/src/cff/t2objs.c
+++ b/src/cff/t2objs.c
@@ -68,7 +68,7 @@
/* face :: The newly built face object. */
/* */
/* <Return> */
- /* FreeTrue error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error T2_Init_Face( FT_Stream stream,
@@ -78,18 +78,12 @@
FT_Parameter* params )
{
FT_Error error;
- FT_Driver sfnt_driver;
SFNT_Interface* sfnt;
+ sfnt = (SFNT_Interface*)
+ FT_Get_Module_Interface( face->root.driver->root.library,"sfnt" );
+ if ( !sfnt ) goto Bad_Format;
- 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;
@@ -163,13 +157,9 @@
void T2_Done_Face( T2_Face face )
{
FT_Memory memory = face->root.memory;
-#if 0
- FT_Stream stream = face->root.stream;
-#endif
SFNT_Interface* sfnt = face->sfnt;
-
if ( sfnt )
sfnt->done_face( face );
@@ -188,151 +178,7 @@
/*************************************************************************/
/* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
/* <Function> */
- /* T2_Init_Size */
- /* */
- /* <Description> */
- /* Initializes a new OpenType size object. */
- /* */
- /* <InOut> */
- /* size :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType 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. */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_DEF
- FT_Error T2_Reset_Size( T2_Size size )
- {
- T2_Face face = (T2_Face)size->face;
- FT_Size_Metrics* metrics = &size->metrics;
-
-
- if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
- return T2_Err_Invalid_PPem;
-
- /* 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 T2_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T2_Init_GlyphSlot */
- /* */
- /* <Description> */
- /* The OpenType glyph slot initializer. */
- /* */
- /* <Input> */
- /* slot :: The glyph record to build. */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error T2_Init_GlyphSlot( T2_GlyphSlot slot )
- {
- FT_Library library = slot->root.face->driver->library;
-
-
- slot->max_points = 0;
- slot->max_contours = 0;
- slot->root.bitmap.buffer = 0;
-
- return FT_Outline_New( library, 0, 0, &slot->root.outline );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T2_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->root.face->driver->library;
- FT_Memory memory = library->memory;
-
-
- if ( slot->root.flags & ft_glyph_own_bitmap )
- FREE( slot->root.bitmap.buffer );
-
- FT_Outline_Done( library, &slot->root.outline );
- return;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
/* T2_Init_Driver */
/* */
/* <Description> */
@@ -342,7 +188,7 @@
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error T2_Init_Driver( T2_Driver driver )
--- a/src/cff/t2objs.h
+++ b/src/cff/t2objs.h
@@ -69,9 +69,6 @@
FT_Bool hint;
FT_Bool scaled;
- FT_Int max_points;
- FT_Int max_contours;
-
FT_Fixed x_scale;
FT_Fixed y_scale;
@@ -118,31 +115,6 @@
LOCAL_DEF
void T2_Done_Face( T2_Face face );
-
-
- /*************************************************************************/
- /* */
- /* Size functions */
- /* */
- 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 functions */
- /* */
- LOCAL_DEF
- FT_Error T2_Init_GlyphSlot( T2_GlyphSlot slot );
-
- LOCAL_DEF
- void T2_Done_GlyphSlot( T2_GlyphSlot slot );
/*************************************************************************/
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -157,9 +157,13 @@
if ( glyph )
{
- builder->base = glyph->root.outline;
- builder->max_points = glyph->max_points;
- builder->max_contours = glyph->max_contours;
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
+
+ FT_GlyphLoader_Rewind(loader);
}
if ( size )
@@ -176,9 +180,6 @@
builder->advance.x = 0;
builder->advance.y = 0;
- builder->base.n_points = 0;
- builder->base.n_contours = 0;
- builder->current = builder->base;
}
@@ -200,13 +201,8 @@
{
T1_GlyphSlot glyph = builder->glyph;
-
if ( glyph )
- {
- glyph->root.outline = builder->base;
- glyph->max_points = builder->max_points;
- glyph->max_contours = builder->max_contours;
- }
+ glyph->root.outline = *builder->base;
}
@@ -236,42 +232,7 @@
FT_Error check_points( CID_Builder* builder,
FT_Int count )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
-
-
- if ( !builder->load_points )
- return T1_Err_Ok;
-
- count += base->n_points + outline->n_points;
-
- /* realloc points table if necessary */
- if ( count >= builder->max_points )
- {
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->points - base->points;
- FT_Int current = builder->max_points;
-
-
- while ( builder->max_points < count )
- builder->max_points += 8;
-
- if ( REALLOC_ARRAY( base->points, current,
- builder->max_points, FT_Vector ) ||
-
- REALLOC_ARRAY( base->tags, current,
- builder->max_points, FT_Byte ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->points = base->points + increment;
- outline->tags = base->tags + increment;
- }
-
- return T1_Err_Ok;
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
}
@@ -282,9 +243,8 @@
FT_Pos y,
FT_Byte flag )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
-
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
@@ -310,7 +270,6 @@
{
FT_Error error;
-
error = check_points( builder, 1 );
if ( !error )
add_point( builder, x, y, 1 );
@@ -323,10 +282,9 @@
static
FT_Error add_contour( CID_Builder* builder )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
+ FT_Error error;
-
if ( !builder->load_points )
{
outline->n_contours++;
@@ -333,34 +291,15 @@
return T1_Err_Ok;
}
- /* realloc contours array if necessary */
- if ( base->n_contours + outline->n_contours >= builder->max_contours &&
- builder->load_points )
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if (!error)
{
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->contours - base->contours;
- FT_Int current = builder->max_contours;
-
-
- builder->max_contours += 4;
-
- if ( REALLOC_ARRAY( base->contours,
- current, builder->max_contours, FT_Short ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->contours = base->contours + increment;
+ if ( outline->n_contours > 0 )
+ outline->contours[outline->n_contours - 1] = outline->n_points - 1;
+
+ outline->n_contours++;
}
-
- if ( outline->n_contours > 0 )
- outline->contours[outline->n_contours - 1] = outline->n_points - 1;
-
- outline->n_contours++;
-
- return T1_Err_Ok;
+ return error;
}
@@ -375,7 +314,6 @@
{
FT_Error error;
-
builder->path_begun = 1;
error = add_contour( builder );
if ( error )
@@ -390,9 +328,8 @@
static
void close_contour( CID_Builder* builder )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
-
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
@@ -473,7 +410,7 @@
/* achar :: The accent character's StandardEncoding charcode. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* Type 1 error code. 0 means success. */
/* */
static
FT_Error t1operator_seac( CID_Decoder* decoder,
@@ -485,11 +422,10 @@
{
FT_Error error;
FT_Int bchar_index, achar_index, n_base_points;
- FT_Outline* cur = &decoder->builder.current;
- FT_Outline* base = &decoder->builder.base;
+ FT_Outline* cur = decoder->builder.current;
+ FT_Outline* base = decoder->builder.base;
FT_Vector left_bearing, advance;
-
bchar_index = bchar;
achar_index = achar;
@@ -499,44 +435,22 @@
return T1_Err_Syntax_Error;
}
- /* First load `bchar' in builder */
- /* now load the unscaled outline */
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
- error = cid_load_glyph( decoder, bchar_index );
- if ( error )
- return error;
-
- n_base_points = cur->n_points;
-
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
if ( decoder->builder.no_recurse )
{
- /* if we are trying to load a composite glyph, do not load the */
- /* accent character and return the array of subglyphs. */
- FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
- FT_SubGlyph* subg;
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
-
/* reallocate subglyph array if necessary */
- if ( glyph->max_subglyphs < 2 )
- {
- FT_Memory memory = decoder->builder.face->root.memory;
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if (error) goto Exit;
+
+ subg = loader->current.subglyphs;
-
- if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
- 2, FT_SubGlyph ) )
- return error;
-
- glyph->max_subglyphs = 2;
- }
-
- subg = glyph->subglyphs;
-
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
@@ -554,8 +468,20 @@
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
}
- else
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+ if (decoder->builder.loader)
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */
+ if ( error ) goto Exit;
+
+ n_base_points = cur->n_points;
+
{
/* save the left bearing and width of the base character */
/* as they will be erased by the next load. */
@@ -568,27 +494,10 @@
/* Now load `achar' on top of */
/* the base outline */
-
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
-
error = cid_load_glyph( decoder, achar_index );
if ( error )
return error;
- /* adjust contours in accented character outline */
- if ( decoder->builder.load_points )
- {
- FT_Int n;
-
-
- for ( n = 0; n < cur->n_contours; n++ )
- cur->contours[n] += n_base_points;
- }
-
/* restore the left side bearing and */
/* advance width of the base character */
@@ -597,10 +506,16 @@
/* Finally, move the accent */
if ( decoder->builder.load_points )
- FT_Outline_Translate( cur, adx - asb, ady );
+ {
+ FT_Outline dummy;
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
}
-
- return T1_Err_Ok;
+ Exit:
+ return error;
}
@@ -626,7 +541,7 @@
/* charstring_len :: The length in bytes of the charstring stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* Type1 error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error CID_Parse_CharStrings( CID_Decoder* decoder,
@@ -654,7 +569,7 @@
ip = zone->cursor = zone->base;
error = T1_Err_Ok;
- outline = &builder->current;
+ outline = builder->current;
x = builder->pos_x;
y = builder->pos_y;
@@ -1011,8 +926,7 @@
close_contour( builder );
/* add current outline to the glyph slot */
- builder->base.n_points += builder->current.n_points;
- builder->base.n_contours += builder->current.n_contours;
+ FT_GlyphLoader_Add( builder->loader );
/* return now! */
FT_TRACE4(( "\n\n" ));
@@ -1535,7 +1449,7 @@
{
/* scale the outline and the metrics */
FT_Int n;
- FT_Outline* cur = &decoder.builder.base;
+ FT_Outline* cur = &glyph->root.outline;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
--- a/src/cid/cidgload.h
+++ b/src/cid/cidgload.h
@@ -80,34 +80,31 @@
/* */
typedef struct CID_Builder_
{
- FT_Memory memory;
- CID_Face face;
- T1_GlyphSlot glyph;
+ FT_Memory memory;
+ CID_Face face;
+ T1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
+ FT_Outline* base;
+ FT_Outline* current;
- FT_Outline current; /* the current glyph outline */
- FT_Outline base; /* the composite glyph outline */
+ FT_Vector last;
- FT_Int max_points; /* capacity of base outline in points */
- FT_Int max_contours; /* capacity of base outline in contours */
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
- FT_Vector last;
+ FT_Pos pos_x;
+ FT_Pos pos_y;
- FT_Fixed scale_x;
- FT_Fixed scale_y;
+ FT_Vector left_bearing;
+ FT_Vector advance;
- FT_Pos pos_x;
- FT_Pos pos_y;
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
- FT_Vector left_bearing;
- FT_Vector advance;
-
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
- FT_Bool no_recurse;
-
- FT_Error error; /* only used for memory errors */
- FT_Bool metrics_only;
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
} CID_Builder;
--- a/src/cid/cidobjs.c
+++ b/src/cid/cidobjs.c
@@ -37,97 +37,6 @@
/*************************************************************************/
/* */
- /* SIZE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* CID_Done_Size */
- /* */
- /* <Description> */
- /* The CID size object finalizer. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
- LOCAL_FUNC
- void CID_Done_Size( T1_Size size )
- {
- UNUSED( size );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* CID_Init_Size */
- /* */
- /* <Description> */
- /* Initializes a new CID size object. */
- /* */
- /* <InOut> */
- /* size :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_DEF
- FT_Error CID_Init_Size( T1_Size size )
- {
- size->valid = 0;
-
- return T1_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* CID_Reset_Size */
- /* */
- /* <Description> */
- /* Resets a OpenType size when resolutions and character dimensions */
- /* have been changed. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error CID_Reset_Size( T1_Size size )
- {
- /* recompute ascender, descender, etc. */
- CID_Face face = (CID_Face)size->root.face;
- FT_Size_Metrics* metrics = &size->root.metrics;
-
-
- if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
- return T1_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 T1_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
/* FACE FUNCTIONS */
/* */
/*************************************************************************/
@@ -201,7 +110,7 @@
/* face :: The newly built face object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* Type1 error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error CID_Init_Face( FT_Stream stream,
@@ -225,13 +134,13 @@
if ( !psnames )
{
/* look-up the PSNames driver */
- FT_Driver psnames_driver;
+ FT_Module psnames_module;
-
- psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
- if ( psnames_driver )
+ psnames_module = FT_Get_Module( face->root.driver->root.library,
+ "psnames" );
+ if (psnames_module)
face->psnames = (PSNames_Interface*)
- (psnames_driver->interface.format_interface);
+ (psnames_module->clazz->module_interface);
}
/* open the tokenizer; this will also check the font format */
@@ -423,60 +332,6 @@
/*************************************************************************/
/* */
/* <Function> */
- /* CID_Done_GlyphSlot */
- /* */
- /* <Description> */
- /* The CID glyph slot finalizer. */
- /* */
- /* <Input> */
- /* slot :: A handle to the glyph slot object. */
- /* */
- LOCAL_FUNC
- void CID_Done_GlyphSlot( T1_GlyphSlot glyph )
- {
- FT_Memory memory = glyph->root.face->memory;
- FT_Library library = glyph->root.face->driver->library;
-
-
- /* the bitmaps are created on demand */
- FREE( glyph->root.bitmap.buffer );
- FT_Outline_Done( library, &glyph->root.outline );
-
- return;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* CID_Init_GlyphSlot */
- /* */
- /* <Description> */
- /* The CID glyph slot initializer. */
- /* */
- /* <Input> */
- /* slot :: The glyph record to build. */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error CID_Init_GlyphSlot( T1_GlyphSlot glyph )
- {
- FT_Library library = glyph->root.face->driver->library;
-
-
- glyph->max_points = 0;
- glyph->max_contours = 0;
- glyph->root.bitmap.buffer = 0;
-
- return FT_Outline_New( library, 0, 0, &glyph->root.outline );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
/* CID_Init_Driver */
/* */
/* <Description> */
@@ -486,7 +341,7 @@
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* Type1 error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error CID_Init_Driver( T1_Driver driver )
@@ -493,7 +348,7 @@
{
UNUSED( driver );
- return T1_Err_Ok;
+ return FT_Err_Ok;
}
--- a/src/cid/cidobjs.h
+++ b/src/cid/cidobjs.h
@@ -95,14 +95,10 @@
{
FT_SizeRec root;
FT_Bool valid;
- T1_Size_Hints* hints; /* defined in the hinter. This allows */
- /* us to experiment with different */
- /* hinting schemes without having to */
- /* change `cidobjs' each time. */
+
} T1_SizeRec;
-
typedef struct T1_GlyphSlotRec_
{
FT_GlyphSlotRec root;
@@ -110,14 +106,9 @@
FT_Bool hint;
FT_Bool scaled;
- FT_Int max_points;
- FT_Int max_contours;
-
FT_Fixed x_scale;
FT_Fixed y_scale;
- T1_Glyph_Hints* hints; /* defined in the hinter */
-
} T1_GlyphSlotRec;
@@ -130,23 +121,6 @@
LOCAL_DEF
void CID_Done_Face( CID_Face face );
-
-
- LOCAL_DEF
- FT_Error CID_Init_Size( T1_Size size );
-
- LOCAL_DEF
- void CID_Done_Size( T1_Size size );
-
- LOCAL_DEF
- FT_Error CID_Reset_Size( T1_Size size );
-
-
- LOCAL_DEF
- FT_Error CID_Init_GlyphSlot( T1_GlyphSlot slot );
-
- LOCAL_DEF
- void CID_Done_GlyphSlot( T1_GlyphSlot slot );
LOCAL_DEF
--- a/src/cid/cidparse.c
+++ b/src/cid/cidparse.c
@@ -67,7 +67,7 @@
/* reallocations. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* Type1 error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error T1_New_Table( T1_Table* table,
@@ -157,7 +157,7 @@
/* length :: The length in bytes of the source object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. An error is returned if */
+ /* Type1 error code. 0 means success. An error is returned if */
/* reallocation fails. */
/* */
LOCAL_FUNC
@@ -934,7 +934,7 @@
if ( strncmp( stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
{
- FT_ERROR(( "[not a valid CID-keyed font]\n" ));
+ FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
error = FT_Err_Unknown_File_Format;
}
--- a/src/cid/cidriver.c
+++ b/src/cid/cidriver.c
@@ -37,36 +37,9 @@
#define FT_COMPONENT trace_ciddriver
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Interface */
- /* */
- /* <Description> */
- /* Each driver can provide one or more extensions to the base */
- /* FreeType API. These can be used to access format specific */
- /* features (e.g., all TrueType/OpenType resources share a common */
- /* file structure and common tables which can be accessed through the */
- /* `sfnt' interface), or more simply generic ones (e.g., the */
- /* `postscript names' interface which can be used to retrieve the */
- /* PostScript name of a given glyph index). */
- /* */
- /* <InOut> */
- /* driver :: A handle to a driver object. */
- /* */
- /* <Input> */
- /* interface :: A string designing the interface. Examples are */
- /* `sfnt', `post_names', `charmaps', etc. */
- /* */
- /* <Return> */
- /* A typeless pointer to the extension's interface (normally a table */
- /* of function pointers). Returns NULL if the requested extension */
- /* isn't available (i.e., wasn't compiled in the driver at build */
- /* time). */
- /* */
static
- FTDriver_Interface Get_Interface( FT_Driver driver,
- const FT_String* interface )
+ FT_Module_Interface CID_Get_Interface( FT_Driver driver,
+ const FT_String* interface )
{
UNUSED( driver );
UNUSED( interface );
@@ -75,154 +48,39 @@
}
-#ifndef T1_CONFIG_OPTION_NO_AFM
+#ifdef xxxT1_CONFIG_OPTION_NO_AFM
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
static
- FT_Error Get_Kerning( T1_Face face,
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_Vector* kerning )
+ FT_Error cid_Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
{
-#if 0
-
T1_AFM* afm;
-#endif
-
kerning->x = 0;
kerning->y = 0;
-#if 0
-
afm = (T1_AFM*)face->afm_data;
if ( afm )
CID_Get_Kerning( afm, left_glyph, right_glyph, kerning );
-#endif /* 0 */
-
return T1_Err_Ok;
}
-#endif /* !T1_CONFIG_OPTION_NO_AFM */
+#endif /* xxxT1_CONFIG_OPTION_NO_AFM */
- /*************************************************************************/
- /* */
- /* <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. */
- /* */
- /* horz_resolution :: The horizontal resolution of the output device. */
- /* */
- /* vert_resolution :: The vertical resolution of the output device. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- static
- FT_Error Set_Char_Sizes( T1_Size size,
- FT_F26Dot6 char_width,
- FT_F26Dot6 char_height,
- FT_UInt horz_resolution,
- FT_UInt vert_resolution )
- {
- UNUSED( char_width );
- UNUSED( char_height );
- UNUSED( horz_resolution );
- UNUSED( vert_resolution );
- size->valid = FALSE;
- return CID_Reset_Size( size );
- }
-
-
/*************************************************************************/
/* */
/* <Function> */
- /* Set_Pixel_Sizes */
+ /* cid_get_char_index */
/* */
/* <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( T1_Size size,
- FT_Int pixel_width,
- FT_Int pixel_height )
- {
- UNUSED( pixel_width );
- UNUSED( pixel_height );
-
- size->valid = FALSE;
- return CID_Reset_Size( size );
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Char_Index */
- /* */
- /* <Description> */
/* Uses a charmap to return a given character code's glyph index. */
/* */
/* <Input> */
@@ -233,14 +91,13 @@
/* Glyph index. 0 means `undefined character code'. */
/* */
static
- FT_UInt Get_Char_Index( FT_CharMap charmap,
- FT_Long charcode )
+ FT_UInt CID_Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
{
T1_Face face;
FT_UInt result = 0;
PSNames_Interface* psnames;
-
face = (T1_Face)charmap->face;
psnames = (PSNames_Interface*)face->psnames;
if ( psnames )
@@ -316,75 +173,55 @@
}
- const FT_DriverInterface t1cid_driver_interface =
+
+ const FT_Driver_Class t1cid_driver_class =
{
- sizeof( FT_DriverRec ),
+ /* firs of all, the FT_Module_Class fields */
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+ "t1cid", /* module name */
+ 0x10000, /* version 1.0 of driver */
+ 0x20000, /* requires FreeType 2.0 */
+
+ 0,
+
+ (FT_Module_Constructor) CID_Init_Driver,
+ (FT_Module_Destructor) CID_Done_Driver,
+ (FT_Module_Requester) CID_Get_Interface
+ },
+
+ /* then the other font drivers fields */
sizeof( CID_FaceRec ),
sizeof( T1_SizeRec ),
sizeof( T1_GlyphSlotRec ),
- "t1cid",
- 100,
- 200,
+ (FTDriver_initFace) CID_Init_Face,
+ (FTDriver_doneFace) CID_Done_Face,
- 0, /* format interface */
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
- (FTDriver_initDriver) CID_Init_Driver,
- (FTDriver_doneDriver) CID_Done_Driver,
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes) 0,
- (FTDriver_getInterface) Get_Interface,
+ (FTDriver_loadGlyph) CID_Load_Glyph,
+ (FTDriver_getCharIndex) CID_Get_Char_Index,
- (FTDriver_initFace) CID_Init_Face,
- (FTDriver_doneFace) CID_Done_Face,
-
-#ifdef T1_CONFIG_OPTION_NO_AFM
- (FTDriver_getKerning) 0,
+#ifndef xxxxT1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
#else
- (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_getKerning) cid_Get_Kerning,
+ (FTDriver_attachFile) CID_Read_AFM,
#endif
- (FTDriver_initSize) CID_Init_Size,
- (FTDriver_doneSize) CID_Done_Size,
- (FTDriver_setCharSizes) Set_Char_Sizes,
- (FTDriver_setPixelSizes)Set_Pixel_Sizes,
-
- (FTDriver_initGlyphSlot)CID_Init_GlyphSlot,
- (FTDriver_doneGlyphSlot)CID_Done_GlyphSlot,
- (FTDriver_loadGlyph) CID_Load_Glyph,
-
- (FTDriver_getCharIndex) Get_Char_Index,
+ (FTDriver_getAdvances) 0
};
-#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* getDriverInterface */
- /* */
- /* <Description> */
- /* This function is used when compiling the CID 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 CID's driver generic interface. The */
- /* format-specific interface can then be retrieved through the method */
- /* interface->get_format_interface. */
- /* */
- EXPORT_FUNC( FT_DriverInterface* ) getDriverInterface( void )
- {
- return &t1cid_driver_interface;
- }
-
-
-#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
/* END */
--- a/src/cid/cidriver.h
+++ b/src/cid/cidriver.h
@@ -22,7 +22,7 @@
#include <cidobjs.h>
#include <freetype/internal/t1errors.h>
- FT_EXPORT_VAR( const FT_DriverInterface ) t1cid_driver_interface;
+ FT_EXPORT_VAR( const FT_Driver_Class ) t1cid_driver_class;
#endif /* CIDRIVER_H */
--- a/src/cid/module.mk
+++ b/src/cid/module.mk
@@ -1,6 +1,6 @@
make_module_list: add_type1cid_driver
add_type1cid_driver:
- $(OPEN_DRIVER)t1cid_driver_interface$(CLOSE_DRIVER)
+ $(OPEN_DRIVER)t1cid_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)cid $(ECHO_DRIVER_DESC)Postscript CID-keyed fonts, no known extension$(ECHO_DRIVER_DONE)
# EOF
--- a/src/psnames/module.mk
+++ b/src/psnames/module.mk
@@ -1,7 +1,7 @@
-make_module_list: add_psnames_driver
+make_module_list: add_psnames_module
-add_psnames_driver:
- $(OPEN_DRIVER)psnames_driver_interface$(CLOSE_DRIVER)
+add_psnames_module:
+ $(OPEN_DRIVER)psnames_module_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)psnames $(ECHO_DRIVER_DESC)Postscript & Unicode Glyph name handling$(ECHO_DRIVER_DONE)
# EOF
--- a/src/psnames/psdriver.h
+++ b/src/psnames/psdriver.h
@@ -1,10 +1,10 @@
/***************************************************************************/
/* */
-/* psdriver.h */
+/* psmodule.h */
/* */
-/* High-level PSNames driver interface (specification). */
+/* High-level PSNames module interface (specification). */
/* */
-/* Copyright 1996-2000 by */
+/* Copyright 1996-1999 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -19,13 +19,11 @@
#ifndef PSDRIVER_H
#define PSDRIVER_H
+#include <freetype/ftmodule.h>
-#include <freetype/internal/ftdriver.h>
+ FT_EXPORT_VAR(const FT_Module_Class) psnames_module_class;
- FT_EXPORT_VAR( const FT_DriverInterface ) psnames_driver_interface;
-
-
-#endif /* PSDRIVER_H */
+#endif /* PSMODULE_H */
/* END */
--- a/src/psnames/psnames.c
+++ b/src/psnames/psnames.c
@@ -1,23 +1,2 @@
-/***************************************************************************/
-/* */
-/* psnames.c */
-/* */
-/* FreeType PSNames driver component (body only). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
-
-
#define FT_MAKE_OPTION_SINGLE_OBJECT
-#include <psdriver.c>
-
-
-/* END */
+#include <psmodule.c>
--- a/src/psnames/rules.mk
+++ b/src/psnames/rules.mk
@@ -31,7 +31,7 @@
# PSNames driver sources (i.e., C files)
#
-PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psdriver.c
+PSNAMES_DRV_SRC := $(PSNAMES_DIR_)psmodule.c
# PSNames driver headers
@@ -50,7 +50,7 @@
# PSNames driver source file for single build
#
-PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psdriver.c
+PSNAMES_DRV_SRC_S := $(PSNAMES_DIR_)psmodule.c
# PSNames driver - single object
--- /dev/null
+++ b/src/renderer/ftgrays.c
@@ -1,0 +1,1952 @@
+/***************************************************************************/
+/* */
+/* ftgrays.c */
+/* */
+/* A new `perfect' anti-aliasing renderer (body). */
+/* */
+/* Copyright 2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This file can be compiled without the rest of the FreeType engine, */
+ /* by defining the _STANDALONE_ macro when compiling it. You also need */
+ /* to put the files `ftgrays.h' and `ftimage.h' into the current */
+ /* compilation directory. Typically, you could do something like */
+ /* */
+ /* - copy `src/base/ftgrays.c' to your current directory */
+ /* */
+ /* - copy `include/freetype/ftimage.h' and */
+ /* `include/freetype/ftgrays.h' to the same directory */
+ /* */
+ /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */
+ /* */
+ /* cc -c -D_STANDALONE_ ftgrays.c */
+ /* */
+ /* The renderer can be initialized with a call to */
+ /* `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be */
+ /* generated with a call to `ft_grays_raster.grays_raster_render'. */
+ /* */
+ /* See the comments and documentation in the file `ftimage.h' for */
+ /* more details on how the raster works. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is a new anti-aliasing scan-converter for FreeType 2. The */
+ /* algorithm used here is _very_ different from the one in the standard */
+ /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
+ /* coverage of the outline on each pixel cell. */
+ /* */
+ /* It is based on ideas that I initially found in Raph Levien's */
+ /* excellent LibArt graphics library (see http://www.levien.com/libart */
+ /* for more information, though the web pages do not tell anything */
+ /* about the renderer; you'll have to dive into the source code to */
+ /* understand how it works). */
+ /* */
+ /* Note, however, that this is a _very_ different implementation */
+ /* compared Raph's. Coverage information is stored in a very different */
+ /* way, and I don't use sorted vector paths. Also, it doesn't use */
+ /* floating point values. */
+ /* */
+ /* This renderer has the following advantages: */
+ /* */
+ /* - It doesn't need an intermediate bitmap. Instead, one can supply */
+ /* a callback function that will be called by the renderer to draw */
+ /* gray spans on any target surface. You can thus do direct */
+ /* composition on any kind of bitmap, provided that you give the */
+ /* renderer the right callback. */
+ /* */
+ /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
+ /* each pixel cell */
+ /* */
+ /* - It performs a single pass on the outline (the `standard' FT2 */
+ /* renderer makes two passes). */
+ /* */
+ /* - It can easily be modified to render to _any_ number of gray levels */
+ /* cheaply. */
+ /* */
+ /* - For small (< 20) pixel sizes, it is faster than the standard */
+ /* renderer. */
+ /* */
+ /*************************************************************************/
+
+
+#include <string.h> /* for memcpy() */
+
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_aaraster
+
+
+#define ErrRaster_Invalid_Outline -1
+
+
+#ifdef _STANDALONE_
+
+
+#include "ftimage.h"
+#include "ftgrays.h"
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+
+#else /* _STANDALONE_ */
+
+
+#include "ftgrays.h"
+#include <freetype/internal/ftobjs.h> /* for UNUSED() */
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+#include <freetype/freetype.h> /* for FT_Outline_Decompose() */
+
+
+#endif /* _STANDALONE_ */
+
+
+ /* define this to dump debugging information */
+#define xxxDEBUG_GRAYS
+
+ /* as usual, for the speed hungry :-) */
+
+#ifndef FT_STATIC_RASTER
+
+
+#define RAS_ARG PRaster raster
+#define RAS_ARG_ PRaster raster,
+
+#define RAS_VAR raster
+#define RAS_VAR_ raster,
+
+#define ras (*raster)
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARG /* empty */
+#define RAS_ARG_ /* empty */
+#define RAS_VAR /* empty */
+#define RAS_VAR_ /* empty */
+
+ static TRaster ras;
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+ /* must be at least 6 bits! */
+#define PIXEL_BITS 8
+
+#define ONE_PIXEL ( 1L << PIXEL_BITS )
+#define PIXEL_MASK ( -1L << PIXEL_BITS )
+#define TRUNC( x ) ( (x) >> PIXEL_BITS )
+#define SUBPIXELS( x ) ( (x) << PIXEL_BITS )
+#define FLOOR( x ) ( (x) & -ONE_PIXEL )
+#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
+#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+
+#if PIXEL_BITS >= 6
+#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
+#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
+#else
+#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
+#endif
+
+ /* Define this if you want to use a more compact storage scheme. This */
+ /* increases the number of cells available in the render pool but slows */
+ /* down the rendering a bit. It is useful if you have a really tiny */
+ /* render pool. */
+#define xxxGRAYS_COMPACT
+
+
+ /*************************************************************************/
+ /* */
+ /* TYPE DEFINITIONS */
+ /* */
+ typedef int TScan; /* integer scanline/pixel coordinate */
+ typedef long TPos; /* sub-pixel coordinate */
+
+ /* maximal number of gray spans in a call to the span callback */
+#define FT_MAX_GRAY_SPANS 32
+
+
+#ifdef GRAYS_COMPACT
+
+ typedef struct TCell_
+ {
+ short x : 14;
+ short y : 14;
+ int cover : PIXEL_BITS + 2;
+ int area : PIXEL_BITS * 2 + 2;
+
+ } TCell, *PCell;
+
+#else /* GRAYS_COMPACT */
+
+ typedef struct TCell_
+ {
+ TScan x;
+ TScan y;
+ int cover;
+ int area;
+
+ } TCell, *PCell;
+
+#endif /* GRAYS_COMPACT */
+
+
+ typedef struct TRaster_
+ {
+ PCell cells;
+ int max_cells;
+ int num_cells;
+
+ TScan min_ex, max_ex;
+ TScan min_ey, max_ey;
+
+ int area;
+ int cover;
+ int invalid;
+
+ TScan ex, ey;
+ TScan cx, cy;
+ TPos x, y;
+
+ TScan last_ey;
+
+ FT_Vector bez_stack[32 * 3];
+ int lev_stack[32];
+
+ FT_Outline outline;
+ FT_Bitmap target;
+
+ FT_Span gray_spans[FT_MAX_GRAY_SPANS];
+ int num_gray_spans;
+
+ FT_Raster_Span_Func render_span;
+ void* render_span_data;
+ int span_y;
+
+ int band_size;
+ int band_shoot;
+ int conic_level;
+ int cubic_level;
+
+ void* memory;
+
+ } TRaster, *PRaster;
+
+
+ /*************************************************************************/
+ /* */
+ /* Initialize the cells table. */
+ /* */
+ static
+ void init_cells( RAS_ARG_ void* buffer,
+ long byte_size )
+ {
+ ras.cells = (PCell)buffer;
+ ras.max_cells = byte_size / sizeof ( TCell );
+ ras.num_cells = 0;
+ ras.area = 0;
+ ras.cover = 0;
+ ras.invalid = 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Compute the outline bounding box. */
+ /* */
+ static
+ void compute_cbox( RAS_ARG_ FT_Outline* outline )
+ {
+ FT_Vector* vec = outline->points;
+ FT_Vector* limit = vec + outline->n_points;
+
+
+ if ( outline->n_points <= 0 )
+ {
+ ras.min_ex = ras.max_ex = 0;
+ ras.min_ey = ras.max_ey = 0;
+ return;
+ }
+
+ ras.min_ex = ras.max_ex = vec->x;
+ ras.min_ey = ras.max_ey = vec->y;
+
+ vec++;
+
+ for ( ; vec < limit; vec++ )
+ {
+ TPos x = vec->x;
+ TPos y = vec->y;
+
+
+ if ( x < ras.min_ex ) ras.min_ex = x;
+ if ( x > ras.max_ex ) ras.max_ex = x;
+ if ( y < ras.min_ey ) ras.min_ey = y;
+ if ( y > ras.max_ey ) ras.max_ey = y;
+ }
+
+ /* truncate the bounding box to integer pixels */
+ ras.min_ex = ras.min_ex >> 6;
+ ras.min_ey = ras.min_ey >> 6;
+ ras.max_ex = ( ras.max_ex + 63 ) >> 6;
+ ras.max_ey = ( ras.max_ey + 63 ) >> 6;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Record the current cell in the table. */
+ /* */
+ static
+ int record_cell( RAS_ARG )
+ {
+ PCell cell;
+
+
+ if ( !ras.invalid && ( ras.area | ras.cover ) )
+ {
+ if ( ras.num_cells >= ras.max_cells )
+ return 1;
+
+ cell = ras.cells + ras.num_cells++;
+ cell->x = ras.ex - ras.min_ex;
+ cell->y = ras.ey - ras.min_ey;
+ cell->area = ras.area;
+ cell->cover = ras.cover;
+ }
+
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Set the current cell to a new position. */
+ /* */
+ static
+ int set_cell( RAS_ARG_ TScan ex,
+ TScan ey )
+ {
+ int invalid, record, clean;
+
+
+ /* Move the cell pointer to a new position. We set the `invalid' */
+ /* flag to indicate that the cell isn't part of those we're interested */
+ /* in during the render phase. This means that: */
+ /* */
+ /* . the new vertical position must be within min_ey..max_ey - 1. */
+ /* . the new horizontal position must be strictly less than max_ex */
+ /* */
+ /* Note that if a cell is to the left of the clipping region, it is */
+ /* actually set to the (min_ex-1) horizontal position. */
+
+ record = 0;
+ clean = 1;
+
+ invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
+ if ( !invalid )
+ {
+ /* All cells that are on the left of the clipping region go to the */
+ /* min_ex - 1 horizontal position. */
+ if ( ex < ras.min_ex )
+ ex = ras.min_ex - 1;
+
+ /* if our position is new, then record the previous cell */
+ if ( ex != ras.ex || ey != ras.ey )
+ record = 1;
+ else
+ clean = ras.invalid; /* do not clean if we didn't move from */
+ /* a valid cell */
+ }
+
+ /* record the previous cell if needed (i.e., if we changed the cell */
+ /* position, of changed the `invalid' flag) */
+ if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) )
+ return 1;
+
+ if ( clean )
+ {
+ ras.area = 0;
+ ras.cover = 0;
+ }
+
+ ras.invalid = invalid;
+ ras.ex = ex;
+ ras.ey = ey;
+ return 0;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Start a new contour at a given cell. */
+ /* */
+ static
+ void start_cell( RAS_ARG_ TScan ex,
+ TScan ey )
+ {
+ if ( ex < ras.min_ex )
+ ex = ras.min_ex - 1;
+
+ ras.area = 0;
+ ras.cover = 0;
+ ras.ex = ex;
+ ras.ey = ey;
+ ras.last_ey = SUBPIXELS( ey );
+ ras.invalid = 0;
+
+ (void)set_cell( RAS_VAR_ ex, ey );
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a scanline as one or more cells. */
+ /* */
+ static
+ int render_scanline( RAS_ARG_ TScan ey,
+ TPos x1,
+ TScan y1,
+ TPos x2,
+ TScan y2 )
+ {
+ TScan ex1, ex2, fx1, fx2, delta;
+ long p, first, dx;
+ int incr, lift, mod, rem;
+
+
+ dx = x2 - x1;
+
+ ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
+ ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
+ fx1 = x1 - SUBPIXELS( ex1 );
+ fx2 = x2 - SUBPIXELS( ex2 );
+
+ /* trivial case. Happens often */
+ if ( y1 == y2 )
+ return set_cell( RAS_VAR_ ex2, ey );
+
+ /* everything is located in a single cell. That is easy! */
+ /* */
+ if ( ex1 == ex2 )
+ {
+ delta = y2 - y1;
+ ras.area += ( fx1 + fx2 ) * delta;
+ ras.cover += delta;
+ return 0;
+ }
+
+ /* ok, we'll have to render a run of adjacent cells on the same */
+ /* scanline... */
+ /* */
+ p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dx < 0 )
+ {
+ p = fx1 * ( y2 - y1 );
+ first = 0;
+ incr = -1;
+ dx = -dx;
+ }
+
+ delta = p / dx;
+ mod = p % dx;
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += dx;
+ }
+
+ ras.area += ( fx1 + first ) * delta;
+ ras.cover += delta;
+
+ ex1 += incr;
+ if ( set_cell( RAS_VAR_ ex1, ey ) )
+ goto Error;
+ y1 += delta;
+
+ if ( ex1 != ex2 )
+ {
+ p = ONE_PIXEL * ( y2 - y1 );
+ lift = p / dx;
+ rem = p % dx;
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += dx;
+ }
+
+ mod -= dx;
+
+ while ( ex1 != ex2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= dx;
+ delta++;
+ }
+
+ ras.area += ONE_PIXEL * delta;
+ ras.cover += delta;
+ y1 += delta;
+ ex1 += incr;
+ if ( set_cell( RAS_VAR_ ex1, ey ) )
+ goto Error;
+ }
+ }
+
+ delta = y2 - y1;
+ ras.area += ( fx2 + ONE_PIXEL - first ) * delta;
+ ras.cover += delta;
+
+ return 0;
+
+ Error:
+ return 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Render a given line as a series of scanlines. */
+ /* */
+ static
+ int render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TScan ey1, ey2, fy1, fy2;
+ TPos dx, dy, x, x2;
+ int p, rem, mod, lift, delta, first, incr;
+
+
+ ey1 = TRUNC( ras.last_ey );
+ ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
+ fy1 = ras.y - ras.last_ey;
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ /* we should do something about the trivial case where dx == 0, */
+ /* as it happens very often! XXXXX */
+
+ /* perform vertical clipping */
+ {
+ TScan min, max;
+
+
+ min = ey1;
+ max = ey2;
+ if ( ey1 > ey2 )
+ {
+ min = ey2;
+ max = ey1;
+ }
+ if ( min >= ras.max_ey || max < ras.min_ey )
+ goto End;
+ }
+
+ /* everything is on a single scanline */
+ if ( ey1 == ey2 )
+ {
+ if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ) )
+ goto Error;
+ goto End;
+ }
+
+ /* ok, we'll have to render several scanlines */
+ p = ( ONE_PIXEL - fy1 ) * dx;
+ first = ONE_PIXEL;
+ incr = 1;
+
+ if ( dy < 0 )
+ {
+ p = fy1 * dx;
+ first = 0;
+ incr = -1;
+ dy = -dy;
+ }
+
+ delta = p / dy;
+ mod = p % dy;
+ if ( mod < 0 )
+ {
+ delta--;
+ mod += dy;
+ }
+
+ x = ras.x + delta;
+ if ( render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first ) )
+ goto Error;
+
+ ey1 += incr;
+ if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+ goto Error;
+
+ if ( ey1 != ey2 )
+ {
+ p = ONE_PIXEL * dx;
+ lift = p / dy;
+ rem = p % dy;
+ if ( rem < 0 )
+ {
+ lift--;
+ rem += dy;
+ }
+ mod -= dy;
+
+ while ( ey1 != ey2 )
+ {
+ delta = lift;
+ mod += rem;
+ if ( mod >= 0 )
+ {
+ mod -= dy;
+ delta++;
+ }
+
+ x2 = x + delta;
+ if ( render_scanline( RAS_VAR_ ey1,
+ x, ONE_PIXEL - first, x2, first ) )
+ goto Error;
+ x = x2;
+ ey1 += incr;
+ if ( set_cell( RAS_VAR_ TRUNC( x ), ey1 ) )
+ goto Error;
+ }
+ }
+
+ if ( render_scanline( RAS_VAR_ ey1,
+ x, ONE_PIXEL - first, to_x, fy2 ) )
+ goto Error;
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ ras.last_ey = SUBPIXELS( ey2 );
+
+ return 0;
+
+ Error:
+ return 1;
+ }
+
+
+ static
+ void split_conic( FT_Vector* base )
+ {
+ TPos a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+ }
+
+
+ static
+ int render_conic( RAS_ARG_ FT_Vector* control,
+ FT_Vector* to )
+ {
+ TPos dx, dy;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+
+ level = 1;
+ dx = dx / ras.conic_level;
+ while ( dx > 0 )
+ {
+ dx >>= 1;
+ level++;
+ }
+
+ /* a shortcut to speed things up */
+ if ( level <= 1 )
+ {
+ /* we compute the mid-point directly in order to avoid */
+ /* calling split_conic() */
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
+ mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
+
+ return render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y );
+ }
+
+ arc = ras.bez_stack;
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control->x );
+ arc[1].y = UPSCALE( control->y );
+ arc[2].x = ras.x;
+ arc[2].y = ras.y;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+ goto Draw;
+
+ split_conic( arc );
+ arc += 2;
+ top++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
+ mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
+
+ if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y ) )
+ return 1;
+
+ top--;
+ arc -= 2;
+ }
+ }
+ return 0;
+ }
+
+
+ static
+ void split_cubic( FT_Vector* base )
+ {
+ TPos a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c ) / 2;
+ base[5].x = b = ( base[3].x + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].x = a = ( a + c ) / 2;
+ base[4].x = b = ( b + c ) / 2;
+ base[3].x = ( a + b ) / 2;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c ) / 2;
+ base[5].y = b = ( base[3].y + d ) / 2;
+ c = ( c + d ) / 2;
+ base[2].y = a = ( a + c ) / 2;
+ base[4].y = b = ( b + c ) / 2;
+ base[3].y = ( a + b ) / 2;
+ }
+
+
+ static
+ int render_cubic( RAS_ARG_ FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to )
+ {
+ TPos dx, dy, da, db;
+ int top, level;
+ int* levels;
+ FT_Vector* arc;
+
+
+ dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ da = dx;
+
+ dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
+ if ( dx < 0 )
+ dx = -dx;
+ dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
+ if ( dy < 0 )
+ dy = -dy;
+ if ( dx < dy )
+ dx = dy;
+ db = dx;
+
+ level = 1;
+ da = da / ras.cubic_level;
+ db = db / ras.conic_level;
+ while ( da > 0 || db > 0 )
+ {
+ da >>= 1;
+ db >>= 2;
+ level++;
+ }
+
+ if ( level <= 1 )
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = UPSCALE( to->x );
+ to_y = UPSCALE( to->y );
+ mid_x = ( ras.x + to_x +
+ 3 * UPSCALE( control1->x + control2->x ) ) / 8;
+ mid_y = ( ras.y + to_y +
+ 3 * UPSCALE( control1->y + control2->y ) ) / 8;
+
+ return render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y );
+ }
+
+ arc = ras.bez_stack;
+ arc[0].x = UPSCALE( to->x );
+ arc[0].y = UPSCALE( to->y );
+ arc[1].x = UPSCALE( control2->x );
+ arc[1].y = UPSCALE( control2->y );
+ arc[2].x = UPSCALE( control1->x );
+ arc[2].y = UPSCALE( control1->y );
+ arc[3].x = ras.x;
+ arc[3].y = ras.y;
+
+ levels = ras.lev_stack;
+ top = 0;
+ levels[0] = level;
+
+ while ( top >= 0 )
+ {
+ level = levels[top];
+ if ( level > 1 )
+ {
+ /* check that the arc crosses the current band */
+ TPos min, max, y;
+
+
+ min = max = arc[0].y;
+ y = arc[1].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[2].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ y = arc[3].y;
+ if ( y < min ) min = y;
+ if ( y > max ) max = y;
+ if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
+ goto Draw;
+ split_cubic( arc );
+ arc += 3;
+ top ++;
+ levels[top] = levels[top - 1] = level - 1;
+ continue;
+ }
+
+ Draw:
+ {
+ TPos to_x, to_y, mid_x, mid_y;
+
+
+ to_x = arc[0].x;
+ to_y = arc[0].y;
+ mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
+ mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+
+ if ( render_line( RAS_VAR_ mid_x, mid_y ) ||
+ render_line( RAS_VAR_ to_x, to_y ) )
+ return 1;
+ top --;
+ arc -= 3;
+ }
+ }
+ return 0;
+ }
+
+
+ /* a macro comparing two cell pointers. Returns true if a <= b. */
+#if 1
+#define PACK( a ) ( ( (long)(a)->y << 16 ) + (a)->x )
+#define LESS_THAN( a, b ) ( PACK( a ) < PACK( b ) )
+#else /* 1 */
+#define LESS_THAN( a, b ) ( (a)->y < (b)->y || \
+ ( (a)->y == (b)->y && (a)->x < (b)->x ) )
+#endif /* 1 */
+
+#define SWAP_CELLS( a, b, temp ) do \
+ { \
+ temp = *(a); \
+ *(a) = *(b); \
+ *(b) = temp; \
+ } while ( 0 )
+#define DEBUG_SORT
+#define QUICK_SORT
+
+#ifdef SHELL_SORT
+
+ /* A simple shell sort algorithm that works directly on our */
+ /* cells table.. */
+ static
+ void shell_sort ( PCell cells,
+ int count )
+ {
+ PCell i, j, limit = cells + count;
+ TCell temp;
+ int gap;
+
+
+ /* compute initial gap */
+ for ( gap = 0; ++gap < count; gap *= 3 )
+ ;
+
+ while ( gap /= 3 )
+ {
+ for ( i = cells + gap; i < limit; i++ )
+ {
+ for ( j = i - gap; ; j -= gap )
+ {
+ PCell k = j + gap;
+
+
+ if ( LESS_THAN( j, k ) )
+ break;
+
+ SWAP_CELLS( j, k, temp );
+
+ if ( j < cells + gap )
+ break;
+ }
+ }
+ }
+ }
+
+#endif /* SHELL_SORT */
+
+
+#ifdef QUICK_SORT
+
+ /* This is a non-recursive quicksort that directly process our cells */
+ /* array. It should be faster than calling the stdlib qsort(), and we */
+ /* can even tailor our insertion threshold... */
+
+#define QSORT_THRESHOLD 9 /* below this size, a sub-array will be sorted */
+ /* through a normal insertion sort.. */
+
+ static
+ void quick_sort( PCell cells,
+ int count )
+ {
+ PCell stack[40]; /* should be enough ;-) */
+ PCell* top; /* top of stack */
+ PCell base, limit;
+ TCell temp;
+
+
+ limit = cells + count;
+ base = cells;
+ top = stack;
+
+ for (;;)
+ {
+ int len = limit - base;
+ PCell i, j, pivot;
+
+
+ if ( len > QSORT_THRESHOLD )
+ {
+ /* we use base + len/2 as the pivot */
+ pivot = base + len / 2;
+ SWAP_CELLS( base, pivot, temp );
+
+ i = base + 1;
+ j = limit - 1;
+
+ /* now ensure that *i <= *base <= *j */
+ if ( LESS_THAN( j, i ) )
+ SWAP_CELLS( i, j, temp );
+
+ if ( LESS_THAN( base, i ) )
+ SWAP_CELLS( base, i, temp );
+
+ if ( LESS_THAN( j, base ) )
+ SWAP_CELLS( base, j, temp );
+
+ for (;;)
+ {
+ do i++; while ( LESS_THAN( i, base ) );
+ do j--; while ( LESS_THAN( base, j ) );
+
+ if ( i > j )
+ break;
+
+ SWAP_CELLS( i, j, temp );
+ }
+
+ SWAP_CELLS( base, j, temp );
+
+ /* now, push the largest sub-array */
+ if ( j - base > limit - i )
+ {
+ top[0] = base;
+ top[1] = j;
+ base = i;
+ }
+ else
+ {
+ top[0] = i;
+ top[1] = limit;
+ limit = j;
+ }
+ top += 2;
+ }
+ else
+ {
+ /* the sub-array is small, perform insertion sort */
+ j = base;
+ i = j + 1;
+
+ for ( ; i < limit; j = i, i++ )
+ {
+ for ( ; LESS_THAN( j + 1, j ); j-- )
+ {
+ SWAP_CELLS( j + 1, j, temp );
+ if ( j == base )
+ break;
+ }
+ }
+ if ( top > stack )
+ {
+ top -= 2;
+ base = top[0];
+ limit = top[1];
+ }
+ else
+ break;
+ }
+ }
+ }
+
+#endif /* QUICK_SORT */
+
+
+#ifdef DEBUG_GRAYS
+#ifdef DEBUG_SORT
+
+ static
+ int check_sort( PCell cells,
+ int count )
+ {
+ PCell p, q;
+
+
+ for ( p = cells + count - 2; p >= cells; p-- )
+ {
+ q = p + 1;
+ if ( !LESS_THAN( p, q ) )
+ return 0;
+ }
+ return 1;
+ }
+
+#endif /* DEBUG_SORT */
+#endif /* DEBUG_GRAYS */
+
+
+ static
+ int Move_To( FT_Vector* to,
+ FT_Raster raster )
+ {
+ TPos x, y;
+
+
+ /* record current cell, if any */
+ record_cell( (PRaster)raster );
+
+ /* start to a new position */
+ x = UPSCALE( to->x );
+ y = UPSCALE( to->y );
+ start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
+ ((PRaster)raster)->x = x;
+ ((PRaster)raster)->y = y;
+ return 0;
+ }
+
+
+ static
+ int Line_To( FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_line( (PRaster)raster,
+ UPSCALE( to->x ), UPSCALE( to->y ) );
+ }
+
+
+ static
+ int Conic_To( FT_Vector* control,
+ FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_conic( (PRaster)raster, control, to );
+ }
+
+
+ static
+ int Cubic_To( FT_Vector* control1,
+ FT_Vector* control2,
+ FT_Vector* to,
+ FT_Raster raster )
+ {
+ return render_cubic( (PRaster)raster, control1, control2, to );
+ }
+
+
+ static
+ void grays_render_span( int y,
+ int count,
+ FT_Span* spans,
+ PRaster raster )
+ {
+ unsigned char* p;
+ FT_Bitmap* map = &raster->target;
+
+
+ /* first of all, compute the scanline offset */
+ p = (unsigned char*)map->buffer - y * map->pitch;
+ if ( map->pitch >= 0 )
+ p += ( map->rows - 1 ) * map->pitch;
+
+ for ( ; count > 0; count--, spans++ )
+ {
+ if ( spans->coverage )
+#if 1
+ memset( p + spans->x, (unsigned char)spans->coverage, spans->len );
+#else /* 1 */
+ {
+ q = p + spans->x;
+ limit = q + spans->len;
+ for ( ; q < limit; q++ )
+ q[0] = (unsigned char)spans->coverage;
+ }
+#endif /* 1 */
+ }
+ }
+
+
+#ifdef DEBUG_GRAYS
+
+#include <stdio.h>
+
+ static
+ void dump_cells( RAS_ARG )
+ {
+ PCell cell, limit;
+ int y = -1;
+
+
+ cell = ras.cells;
+ limit = cell + ras.num_cells;
+
+ for ( ; cell < limit; cell++ )
+ {
+ if ( cell->y != y )
+ {
+ fprintf( stderr, "\n%2d: ", cell->y );
+ y = cell->y;
+ }
+ fprintf( stderr, "[%d %d %d]",
+ cell->x, cell->area, cell->cover );
+ }
+ fprintf(stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+
+ static
+ void grays_hline( RAS_ARG_ TScan x,
+ TScan y,
+ TPos area,
+ int acount )
+ {
+ FT_Span* span;
+ int count;
+ int coverage;
+
+
+ /* compute the coverage line's coverage, depending on the */
+ /* outline fill rule */
+ /* */
+ /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
+ /* */
+ coverage = area >> ( PIXEL_BITS * 2 + 1 - 8); /* use range 0..256 */
+
+ if ( ras.outline.flags & ft_outline_even_odd_fill )
+ {
+ if ( coverage < 0 )
+ coverage = -coverage;
+
+ while ( coverage >= 512 )
+ coverage -= 512;
+
+ if ( coverage > 256 )
+ coverage = 512 - coverage;
+ else if ( coverage == 256 )
+ coverage = 255;
+ }
+ else
+ {
+ /* normal non-zero winding rule */
+ if ( coverage < 0 )
+ coverage = -coverage;
+
+ if ( coverage >= 256 )
+ coverage = 255;
+ }
+
+ y += ras.min_ey;
+ x += ras.min_ex;
+
+ if ( coverage )
+ {
+ /* see if we can add this span to the current list */
+ count = ras.num_gray_spans;
+ span = ras.gray_spans + count - 1;
+ if ( count > 0 &&
+ ras.span_y == y &&
+ (int)span->x + span->len == (int)x &&
+ span->coverage == coverage )
+ {
+ span->len += acount;
+ return;
+ }
+
+ if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
+ {
+ if ( ras.render_span )
+ ras.render_span( ras.span_y, count, ras.gray_spans,
+ ras.render_span_data );
+ /* ras.render_span( span->y, ras.gray_spans, count ); */
+
+#ifdef DEBUG_GRAYS
+
+ if ( ras.span_y >= 0 )
+ {
+ int n;
+
+
+ fprintf( stderr, "y=%3d ", ras.span_y );
+ span = ras.gray_spans;
+ for ( n = 0; n < count; n++, span++ )
+ fprintf( stderr, "[%d..%d]:%02x ",
+ span->x, span->x + span->len - 1, span->coverage );
+ fprintf( stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+ ras.num_gray_spans = 0;
+ ras.span_y = y;
+
+ count = 0;
+ span = ras.gray_spans;
+ }
+ else
+ span++;
+
+ /* add a gray span to the current list */
+ span->x = (short)x;
+ span->len = (unsigned short)acount;
+ span->coverage = (unsigned char)coverage;
+ ras.num_gray_spans++;
+ }
+ }
+
+
+ static
+ void grays_sweep( RAS_ARG_ FT_Bitmap* target )
+ {
+ TScan x, y, cover, area;
+ PCell start, cur, limit;
+
+ UNUSED( target );
+
+
+ cur = ras.cells;
+ limit = cur + ras.num_cells;
+
+ cover = 0;
+ ras.span_y = -1;
+ ras.num_gray_spans = 0;
+
+ for (;;)
+ {
+ start = cur;
+ y = start->y;
+ x = start->x;
+
+ area = start->area;
+ cover += start->cover;
+
+ /* accumulate all start cells */
+ for (;;)
+ {
+ ++cur;
+ if ( cur >= limit || cur->y != start->y || cur->x != start->x )
+ break;
+
+ area += cur->area;
+ cover += cur->cover;
+ }
+
+ /* if the start cell has a non-null area, we must draw an */
+ /* individual gray pixel there */
+ if ( area && x >= 0 )
+ {
+ grays_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
+ x++;
+ }
+
+ if ( x < 0 )
+ x = 0;
+
+ if ( cur < limit && start->y == cur->y )
+ {
+ /* draw a gray span between the start cell and the current one */
+ if ( cur->x > x )
+ grays_hline( RAS_VAR_ x, y,
+ cover * ( ONE_PIXEL * 2 ), cur->x - x );
+ }
+ else
+ {
+ /* draw a gray span until the end of the clipping region */
+ if ( cover && x < ras.max_ex - ras.min_ex )
+ grays_hline( RAS_VAR_ x, y,
+ cover * ( ONE_PIXEL * 2 ),
+ ras.max_ex - x - ras.min_ex );
+ cover = 0;
+ }
+
+ if ( cur >= limit )
+ break;
+ }
+
+ if ( ras.render_span && ras.num_gray_spans > 0 )
+ ras.render_span( ras.span_y, ras.num_gray_spans,
+ ras.gray_spans, ras.render_span_data );
+
+#ifdef DEBUG_GRAYS
+
+ {
+ int n;
+ FT_Span* span;
+
+
+ fprintf( stderr, "y=%3d ", ras.span_y );
+ span = ras.gray_spans;
+ for ( n = 0; n < ras.num_gray_spans; n++, span++ )
+ fprintf( stderr, "[%d..%d]:%02x ",
+ span->x, span->x + span->len - 1, span->coverage );
+ fprintf( stderr, "\n" );
+ }
+
+#endif /* DEBUG_GRAYS */
+
+ }
+
+
+#ifdef _STANDALONE_
+
+ /*************************************************************************/
+ /* */
+ /* The following function should only compile in stand_alone mode, */
+ /* i.e., when building this component without the rest of FreeType. */
+ /* */
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* FT_Outline_Decompose */
+ /* */
+ /* <Description> */
+ /* Walks over an outline's structure to decompose it into individual */
+ /* segments and Bezier arcs. This function is also able to emit */
+ /* `move to' and `close to' operations to indicate the start and end */
+ /* of new contours in the outline. */
+ /* */
+ /* <Input> */
+ /* outline :: A pointer to the source target. */
+ /* */
+ /* interface :: A table of `emitters', i.e,. function pointers called */
+ /* during decomposition to indicate path operations. */
+ /* */
+ /* user :: A typeless pointer which is passed to each emitter */
+ /* during the decomposition. It can be used to store */
+ /* the state during the decomposition. */
+ /* */
+ /* <Return> */
+ /* Error code. 0 means sucess. */
+ /* */
+ static
+ int FT_Outline_Decompose( FT_Outline* outline,
+ FT_Outline_Funcs* interface,
+ void* user )
+ {
+#undef SCALED
+#define SCALED( x ) ( ( (x) << shift ) - delta )
+
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ int n; /* index of contour in outline */
+ int first; /* index of first point in contour */
+ int error;
+ char tag; /* current point's state */
+
+ int shift = interface->shift;
+ FT_Pos delta = interface->delta;
+
+
+ first = 0;
+
+ for ( n = 0; n < outline->n_contours; n++ )
+ {
+ int last; /* index of last point in contour */
+
+
+ last = outline->contours[n];
+ limit = outline->points + last;
+
+ v_start = outline->points[first];
+ v_last = outline->points[last];
+
+ v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
+ v_last.x = SCALED( v_last.x ); v_last.y = SCALED( v_last.y );
+
+ v_control = v_start;
+
+ point = outline->points + first;
+ tags = outline->tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_Curve_Tag_Conic )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ error = interface->move_to( &v_start, user );
+ if ( error )
+ goto Exit;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+ switch ( tag )
+ {
+ case FT_Curve_Tag_On: /* emit a single line_to */
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->line_to( &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ case FT_Curve_Tag_Conic: /* consume conic arcs */
+ {
+ v_control.x = SCALED( point->x );
+ v_control.y = SCALED( point->y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector vec;
+ FT_Vector v_middle;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ if ( tag == FT_Curve_Tag_On )
+ {
+ error = interface->conic_to( &v_control, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ if ( tag != FT_Curve_Tag_Conic )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + vec.x ) / 2;
+ v_middle.y = ( v_control.y + vec.y ) / 2;
+
+ error = interface->conic_to( &v_control, &v_middle, user );
+ if ( error )
+ goto Exit;
+
+ v_control = vec;
+ goto Do_Conic;
+ }
+
+ error = interface->conic_to( &v_control, &v_start, user );
+ goto Close;
+ }
+
+ default: /* FT_Curve_Tag_Cubic */
+ {
+ FT_Vector vec1, vec2;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
+ vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
+
+ if ( point <= limit )
+ {
+ FT_Vector vec;
+
+
+ vec.x = SCALED( point->x );
+ vec.y = SCALED( point->y );
+
+ error = interface->cubic_to( &vec1, &vec2, &vec, user );
+ if ( error )
+ goto Exit;
+ continue;
+ }
+
+ error = interface->cubic_to( &vec1, &vec2, &v_start, user );
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ error = interface->line_to( &v_start, user );
+
+ Close:
+ if ( error )
+ goto Exit;
+
+ first = last + 1;
+ }
+
+ return 0;
+
+ Exit:
+ return error;
+
+ Invalid_Outline:
+ return ErrRaster_Invalid_Outline;
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ typedef struct TBand_
+ {
+ FT_Pos min, max;
+
+ } TBand;
+
+
+ static
+ int grays_convert_glyph( RAS_ARG_ FT_Outline* outline )
+ {
+ static
+ FT_Outline_Funcs interface =
+ {
+ (FT_Outline_MoveTo_Func)Move_To,
+ (FT_Outline_LineTo_Func)Line_To,
+ (FT_Outline_ConicTo_Func)Conic_To,
+ (FT_Outline_CubicTo_Func)Cubic_To,
+ 0,
+ 0
+ };
+
+ TBand bands[40], *band;
+ int n, num_bands;
+ TPos min, max, max_y;
+
+
+ /* Set up state in the raster object */
+ compute_cbox( RAS_VAR_ outline );
+
+ /* clip to target bitmap, exit if nothing to do */
+ if ( ras.max_ex <= 0 || ras.min_ex >= ras.target.width ||
+ ras.max_ey <= 0 || ras.min_ey >= ras.target.rows )
+ return 0;
+
+ if ( ras.min_ex < 0 ) ras.min_ex = 0;
+ if ( ras.min_ey < 0 ) ras.min_ey = 0;
+
+ if ( ras.max_ex > ras.target.width ) ras.max_ex = ras.target.width;
+ if ( ras.max_ey > ras.target.rows ) ras.max_ey = ras.target.rows;
+
+ /* simple heuristic used to speed-up the bezier decomposition */
+ /* see the code in render_conic and render_cubic for more details */
+ ras.conic_level = 32;
+ ras.cubic_level = 16;
+
+ {
+ int level = 0;
+
+
+ if ( ras.max_ex > 24 || ras.max_ey > 24 )
+ level++;
+ if ( ras.max_ex > 120 || ras.max_ey > 120 )
+ level += 2;
+
+ ras.conic_level <<= level;
+ ras.cubic_level <<= level;
+ }
+
+ /* setup vertical bands */
+ num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
+ if ( num_bands == 0 ) num_bands = 1;
+ if ( num_bands >= 39 ) num_bands = 39;
+
+ ras.band_shoot = 0;
+
+ min = ras.min_ey;
+ max_y = ras.max_ey;
+
+ for ( n = 0; n < num_bands; n++, min = max )
+ {
+ max = min + ras.band_size;
+ if ( n == num_bands - 1 || max > max_y )
+ max = max_y;
+
+ bands[0].min = min;
+ bands[0].max = max;
+ band = bands;
+
+ while ( band >= bands )
+ {
+ FT_Pos bottom, top, middle;
+ int error;
+
+
+ ras.num_cells = 0;
+ ras.invalid = 1;
+ ras.min_ey = band->min;
+ ras.max_ey = band->max;
+
+ error = FT_Outline_Decompose( outline, &interface, &ras ) ||
+ record_cell( RAS_VAR );
+
+ if ( !error )
+ {
+#ifdef SHELL_SORT
+ shell_sort( ras.cells, ras.num_cells );
+#else
+ quick_sort( ras.cells, ras.num_cells );
+#endif
+
+#ifdef DEBUG_GRAYS
+ check_sort( ras.cells, ras.num_cells );
+ dump_cells( RAS_VAR );
+#endif
+
+ grays_sweep( RAS_VAR_ &ras.target );
+ band--;
+ continue;
+ }
+
+ /* render pool overflow, we will reduce the render band by half */
+ bottom = band->min;
+ top = band->max;
+ middle = bottom + ( ( top - bottom ) >> 1 );
+
+ /* waoow! This is too complex for a single scanline, something */
+ /* must be really rotten here! */
+ if ( middle == bottom )
+ {
+#ifdef DEBUG_GRAYS
+ fprintf( stderr, "Rotten glyph!\n" );
+#endif
+ return 1;
+ }
+
+ if ( bottom-top >= ras.band_size )
+ ras.band_shoot++;
+
+ band[1].min = bottom;
+ band[1].max = middle;
+ band[0].min = middle;
+ band[0].max = top;
+ band++;
+ }
+ }
+
+ if ( ras.band_shoot > 8 && ras.band_size > 16 )
+ ras.band_size = ras.band_size / 2;
+
+ return 0;
+ }
+
+
+ extern
+ int grays_raster_render( PRaster raster,
+ FT_Raster_Params* params )
+ {
+ FT_Outline* outline = (FT_Outline*)params->source;
+ FT_Bitmap* target_map = params->target;
+
+
+ if ( !raster || !raster->cells || !raster->max_cells )
+ return -1;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return 0;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return ErrRaster_Invalid_Outline;
+
+ if ( outline->n_points !=
+ outline->contours[outline->n_contours - 1] + 1 )
+ return ErrRaster_Invalid_Outline;
+
+ if ( !target_map || !target_map->buffer )
+ return -1;
+
+ /* XXXX: this version does not support monochrome rendering yet! */
+ if ( !(params->flags & ft_raster_flag_aa) )
+ return -1;
+
+ ras.outline = *outline;
+ ras.target = *target_map;
+ ras.num_cells = 0;
+ ras.invalid = 1;
+
+ ras.render_span = (FT_Raster_Span_Func)grays_render_span;
+ ras.render_span_data = &ras;
+
+ if ( params->flags & ft_raster_flag_direct )
+ {
+ ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
+ ras.render_span_data = params->user;
+ }
+
+ return grays_convert_glyph( (PRaster)raster, outline );
+ }
+
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+#ifdef _STANDALONE_
+
+ static
+ int grays_raster_new( void* memory,
+ FT_Raster* araster )
+ {
+ static TRaster the_raster;
+
+ UNUSED( memory );
+
+
+ *araster = (FT_Raster)&the_raster;
+ memset( &the_raster, 0, sizeof ( the_raster ) );
+
+ return 0;
+ }
+
+
+ static
+ void grays_raster_done( FT_Raster raster )
+ {
+ /* nothing */
+ UNUSED( raster );
+ }
+
+#else /* _STANDALONE_ */
+
+ static
+ int grays_raster_new( FT_Memory memory,
+ FT_Raster* araster )
+ {
+ FT_Error error;
+ PRaster raster;
+
+
+ *araster = 0;
+ if ( !ALLOC( raster, sizeof ( TRaster ) ) )
+ {
+ raster->memory = memory;
+ *araster = (FT_Raster)raster;
+ }
+
+ return error;
+ }
+
+
+ static
+ void grays_raster_done( FT_Raster raster )
+ {
+ FT_Memory memory = (FT_Memory)((PRaster)raster)->memory;
+
+
+ FREE( raster );
+ }
+
+#endif /* _STANDALONE_ */
+
+
+ static
+ void grays_raster_reset( FT_Raster raster,
+ const char* pool_base,
+ long pool_size )
+ {
+ PRaster rast = (PRaster)raster;
+
+
+ if ( raster && pool_base && pool_size >= 4096 )
+ init_cells( rast, (char*)pool_base, pool_size );
+
+ rast->band_size = ( pool_size / sizeof ( TCell ) ) / 8;
+ }
+
+
+ FT_Raster_Funcs ft_grays_raster =
+ {
+ ft_glyph_format_outline,
+
+ (FT_Raster_New_Func) grays_raster_new,
+ (FT_Raster_Reset_Func) grays_raster_reset,
+ (FT_Raster_Set_Mode_Func)0,
+ (FT_Raster_Render_Func) grays_raster_render,
+ (FT_Raster_Done_Func) grays_raster_done
+ };
+
+
+/* END */
--- /dev/null
+++ b/src/renderer/ftgrays.h
@@ -1,0 +1,49 @@
+/***************************************************************************/
+/* */
+/* ftgrays.h */
+/* */
+/* FreeType smooth renderer declaration */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#ifndef FTGRAYS_H
+#define FTGRAYS_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#ifdef _STANDALONE_
+#include "ftimage.h"
+#else
+#include <freetype/ftimage.h>
+#endif
+
+ /*************************************************************************/
+ /* */
+ /* To make ftgrays.h independent from configuration files we check */
+ /* whether FT_EXPORT_DEF has been defined already. */
+ /* */
+ /* On some systems and compilers (Win32 mostly), an extra keyword is */
+ /* necessary to compile the library as a DLL. */
+ /* */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR(x) extern x
+#endif
+
+ FT_EXPORT_VAR(FT_Raster_Funcs) ft_grays_raster;
+
+ #ifdef __cplusplus
+ }
+ #endif
+
+#endif
--- /dev/null
+++ b/src/renderer/ftraster.c
@@ -1,0 +1,3262 @@
+/***************************************************************************/
+/* */
+/* ftraster.c */
+/* */
+/* The FreeType glyph rasterizer (body). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* This is a rewrite of the FreeType 1.x scan-line converter */
+ /* */
+ /*************************************************************************/
+
+
+#include "ftraster.h"
+#include <freetype/internal/ftcalc.h> /* for FT_MulDiv() only */
+
+
+ /*************************************************************************/
+ /* */
+ /* A simple technical note on how the raster works: */
+ /* */
+ /* Converting an outline into a bitmap is achieved in several steps: */
+ /* */
+ /* 1 - Decomposing the outline into successive `profiles'. Each */
+ /* profile is simply an array of scanline intersections on a given */
+ /* dimension. A profile's main attributes are */
+ /* */
+ /* o its scanline position boundaries, i.e. `Ymin' and `Ymax'. */
+ /* */
+ /* o an array of intersection coordinates for each scanline */
+ /* between `Ymin' and `Ymax'. */
+ /* */
+ /* o a direction, indicating whether it was built going `up' or */
+ /* `down', as this is very important for filling rules. */
+ /* */
+ /* 2 - Sweeping the target map's scanlines in order to compute segment */
+ /* `spans' which are then filled. Additionally, this pass */
+ /* performs drop-out control. */
+ /* */
+ /* The outline data is parsed during step 1 only. The profiles are */
+ /* built from the bottom of the render pool, used as a stack. The */
+ /* following graphics shows the profile list under construction: */
+ /* */
+ /* ____________________________________________________________ _ _ */
+ /* | | | | | */
+ /* | profile | coordinates for | profile | coordinates for |--> */
+ /* | 1 | profile 1 | 2 | profile 2 |--> */
+ /* |_________|___________________|_________|_________________|__ _ _ */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* start of render pool top */
+ /* */
+ /* The top of the profile stack is kept in the `top' variable. */
+ /* */
+ /* As you can see, a profile record is pushed on top of the render */
+ /* pool, which is then followed by its coordinates/intersections. If */
+ /* a change of direction is detected in the outline, a new profile is */
+ /* generated until the end of the outline. */
+ /* */
+ /* Note that when all profiles have been generated, the function */
+ /* Finalize_Profile_Table() is used to record, for each profile, its */
+ /* bottom-most scanline as well as the scanline above its upmost */
+ /* boundary. These positions are called `y-turns' because they (sort */
+ /* of) correspond to local extrema. They are stored in a sorted list */
+ /* built from the top of the render pool as a downwards stack: */
+ /* */
+ /* _ _ _______________________________________ */
+ /* | | */
+ /* <--| sorted list of | */
+ /* <--| extrema scanlines | */
+ /* _ _ __________________|____________________| */
+ /* */
+ /* ^ ^ */
+ /* | | */
+ /* maxBuff sizeBuff = end of pool */
+ /* */
+ /* This list is later used during the sweep phase in order to */
+ /* optimize performance (see technical note on the sweep below). */
+ /* */
+ /* Of course, the raster detects whether the two stacks collide and */
+ /* handles the situation propertly. */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** CONFIGURATION MACROS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+ /* The default render pool size in bytes */
+#define RASTER_RENDER_POOL 8192
+
+ /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+ /* 5-levels anti-aliasing */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+ /* The size of the two-lines intermediate bitmap used */
+ /* for anti-aliasing, in bytes. */
+#define RASTER_GRAY_LINES 2048
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** OTHER MACROS (do not change) **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ /*************************************************************************/
+ /* */
+ /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
+ /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
+ /* messages during execution. */
+ /* */
+#undef FT_COMPONENT
+#define FT_COMPONENT trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+ /* This macro is used to indicate that a function parameter is unused. */
+ /* Its purpose is simply to reduce compiler warnings. Note also that */
+ /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+ /* ANSI compilers (e.g. LCC). */
+#define UNUSED( x ) (x) = (x)
+
+ /* Disable the tracing mechanism for simplicity -- developers can */
+ /* activate it easily by redefining these two macros. */
+#ifndef FT_ERROR
+#define FT_ERROR( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x ) do ; while ( 0 ) /* nothing */
+#endif
+
+
+#else /* _STANDALONE_ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
+
+
+#endif /* _STANDALONE_ */
+
+
+#define Raster_Err_None 0
+#define Raster_Err_Not_Ini -1
+#define Raster_Err_Overflow -2
+#define Raster_Err_Neg_Height -3
+#define Raster_Err_Invalid -4
+#define Raster_Err_Gray_Unsupported -5
+#define Raster_Err_Unsupported -6
+
+ /* FMulDiv means `Fast MulDiv', it is used in case where `b' is */
+ /* typically a small value and the result of a*b is known to fit into */
+ /* 32 bits. */
+#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
+
+ /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+ /* for clipping computations. It simply uses the FT_MulDiv() function */
+ /* defined in `ftcalc.h'. */
+#define SMulDiv FT_MulDiv
+
+ /* The rasterizer is a very general purpose component; please leave */
+ /* the following redefinitions there (you never know your target */
+ /* environment). */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+
+#ifndef FAILURE
+#define FAILURE 1
+#endif
+
+
+#define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
+ /* Setting this constant to more than 32 is a */
+ /* pure waste of space. */
+
+#define Pixel_Bits 6 /* fractional bits of *input* coordinates */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SIMPLE TYPE DECLARATIONS **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ typedef int Int;
+ typedef unsigned int UInt;
+ typedef short Short;
+ typedef unsigned short UShort, *PUShort;
+ typedef long Long, *PLong;
+ typedef unsigned long ULong;
+
+ typedef unsigned char Byte, *PByte;
+ typedef char Bool;
+
+ typedef struct TPoint_
+ {
+ Long x;
+ Long y;
+
+ } TPoint;
+
+
+ typedef enum TFlow_
+ {
+ Flow_None = 0,
+ Flow_Up = 1,
+ Flow_Down = -1
+
+ } TFlow;
+
+
+ /* States of each line, arc, and profile */
+ typedef enum TStates_
+ {
+ Unknown,
+ Ascending,
+ Descending,
+ Flat
+
+ } TStates;
+
+
+ typedef struct TProfile_ TProfile;
+ typedef TProfile* PProfile;
+
+ struct TProfile_
+ {
+ FT_F26Dot6 X; /* current coordinate during sweep */
+ PProfile link; /* link to next profile - various purpose */
+ PLong offset; /* start of profile's data in render pool */
+ Int flow; /* Profile orientation: Asc/Descending */
+ Long height; /* profile's height in scanlines */
+ Long start; /* profile's starting scanline */
+
+ UShort countL; /* number of lines to step before this */
+ /* profile becomes drawable */
+
+ PProfile next; /* next profile in same contour, used */
+ /* during drop-out control */
+ };
+
+ typedef PProfile TProfileList;
+ typedef PProfile* PProfileList;
+
+
+ /* Simple record used to implement a stack of bands, required */
+ /* by the sub-banding mechanism */
+ typedef struct TBand_
+ {
+ Short y_min; /* band's minimum */
+ Short y_max; /* band's maximum */
+
+ } TBand;
+
+
+#define AlignProfileSize \
+ ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef TT_STATIC_RASTER
+
+#define RAS_ARGS /* void */
+#define RAS_ARG /* void */
+
+#define RAS_VARS /* void */
+#define RAS_VAR /* void */
+
+#define UNUSED_RASTER do ; while ( 0 )
+
+#else /* TT_STATIC_RASTER */
+
+#define RAS_ARGS TRaster_Instance* raster,
+#define RAS_ARG TRaster_Instance* raster
+
+#define RAS_VARS raster,
+#define RAS_VAR raster
+
+#define UNUSED_RASTER UNUSED( raster )
+
+#endif /* TT_STATIC_RASTER */
+
+
+ typedef struct TRaster_Instance_ TRaster_Instance;
+
+
+ /* prototypes used for sweep function dispatch */
+ typedef void Function_Sweep_Init( RAS_ARGS Short* min,
+ Short* max );
+
+ typedef void Function_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right );
+
+ typedef void Function_Sweep_Step( RAS_ARG );
+
+
+ /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x ) ( (x) & -ras.precision )
+#define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+ /* Note that I have moved the location of some fields in the */
+ /* structure to ensure that the most used variables are used */
+ /* at the top. Thus, their offset can be coded with less */
+ /* opcodes, and it results in a smaller executable. */
+
+ struct TRaster_Instance_
+ {
+ Int precision_bits; /* precision related variables */
+ Int precision;
+ Int precision_half;
+ Long precision_mask;
+ Int precision_shift;
+ Int precision_step;
+ Int precision_jitter;
+
+ Int scale_shift; /* == precision_shift for bitmaps */
+ /* == precision_shift+1 for pixmaps */
+
+ PLong buff; /* The profiles buffer */
+ PLong sizeBuff; /* Render pool size */
+ PLong maxBuff; /* Profiles buffer size */
+ PLong top; /* Current cursor in buffer */
+
+ FT_Error error;
+
+ Int numTurns; /* number of Y-turns in outline */
+
+ TPoint* arc; /* current Bezier arc pointer */
+
+ UShort bWidth; /* target bitmap width */
+ PByte bTarget; /* target bitmap buffer */
+ PByte gTarget; /* target pixmap buffer */
+
+ Long lastX, lastY, minY, maxY;
+
+ UShort num_Profs; /* current number of profiles */
+
+ Bool fresh; /* signals a fresh new profile which */
+ /* 'start' field must be completed */
+ Bool joint; /* signals that the last arc ended */
+ /* exactly on a scanline. Allows */
+ /* removal of doublets */
+ PProfile cProfile; /* current profile */
+ PProfile fProfile; /* head of linked list of profiles */
+ PProfile gProfile; /* contour's first profile in case */
+ /* of impact */
+ TStates state; /* rendering state */
+
+ FT_Bitmap target; /* description of target bit/pixmap */
+ FT_Outline outline;
+
+ Long traceOfs; /* current offset in target bitmap */
+ Long traceG; /* current offset in target pixmap */
+
+ Short traceIncr; /* sweep's increment in target bitmap */
+
+ Short gray_min_x; /* current min x during gray rendering */
+ Short gray_max_x; /* current max x during gray rendering */
+
+ /* dispatch variables */
+
+ Function_Sweep_Init* Proc_Sweep_Init;
+ Function_Sweep_Span* Proc_Sweep_Span;
+ Function_Sweep_Span* Proc_Sweep_Drop;
+ Function_Sweep_Step* Proc_Sweep_Step;
+
+ Byte dropOutControl; /* current drop_out control method */
+
+ Bool second_pass; /* indicates wether a horizontal pass */
+ /* should be performed to control */
+ /* drop-out accurately when calling */
+ /* Render_Glyph. Note that there is */
+ /* no horizontal pass during gray */
+ /* rendering. */
+ TPoint arcs[2 * MaxBezier + 1]; /* The Bezier stack */
+
+ TBand band_stack[16]; /* band stack used for sub-banding */
+ Int band_top; /* band stack top */
+
+ Int count_table[256]; /* Look-up table used to quickly count */
+ /* set bits in a gray 2x2 cell */
+
+ void* memory;
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+ Byte grays[5]; /* Palette of gray levels used for */
+ /* render. */
+
+ Byte gray_lines[RASTER_GRAY_LINES];
+ /* Intermediate table used to render the */
+ /* graylevels pixmaps. */
+ /* gray_lines is a buffer holding two */
+ /* monochrome scanlines */
+ Short gray_width; /* width in bytes of one monochrome */
+ /* intermediate scanline of gray_lines. */
+ /* Each gray pixel takes 2 bits long there */
+
+ /* The gray_lines must hold 2 lines, thus with size */
+ /* in bytes of at least `gray_width*2'. */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+#if 0
+ PByte flags; /* current flags table */
+ PUShort outs; /* current outlines table */
+ FT_Vector* coords;
+
+ UShort nPoints; /* number of points in current glyph */
+ Short nContours; /* number of contours in current glyph */
+#endif
+
+ };
+
+
+#ifdef FT_CONFIG_OPTION_STATIC_RASTER
+
+ static TRaster_Instance cur_ras;
+#define ras cur_ras
+
+#else
+
+#define ras (*raster)
+
+#endif /* FT_CONFIG_OPTION_STATIC_RASTER */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** PROFILES COMPUTATION **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Set_High_Precision */
+ /* */
+ /* <Description> */
+ /* Sets precision variables according to param flag. */
+ /* */
+ /* <Input> */
+ /* High :: Set to True for high precision (typically for ppem < 18), */
+ /* false otherwise. */
+ /* */
+ static
+ void Set_High_Precision( RAS_ARGS Int High )
+ {
+ if ( High )
+ {
+ ras.precision_bits = 10;
+ ras.precision_step = 128;
+ ras.precision_jitter = 24;
+ }
+ else
+ {
+ ras.precision_bits = 6;
+ ras.precision_step = 32;
+ ras.precision_jitter = 2;
+ }
+
+ FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+ ras.precision = 1L << ras.precision_bits;
+ ras.precision_half = ras.precision / 2;
+ ras.precision_shift = ras.precision_bits - Pixel_Bits;
+ ras.precision_mask = -ras.precision;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* New_Profile */
+ /* */
+ /* <Description> */
+ /* Creates a new profile in the render pool. */
+ /* */
+ /* <Input> */
+ /* aState :: The state/orientation of the new profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
+ /* profile. */
+ /* */
+ static
+ Bool New_Profile( RAS_ARGS TStates aState )
+ {
+ if ( !ras.fProfile )
+ {
+ ras.cProfile = (PProfile)ras.top;
+ ras.fProfile = ras.cProfile;
+ ras.top += AlignProfileSize;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ switch ( aState )
+ {
+ case Ascending:
+ ras.cProfile->flow = Flow_Up;
+ FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ case Descending:
+ ras.cProfile->flow = Flow_Down;
+ FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+ break;
+
+ default:
+ FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ ras.cProfile->start = 0;
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ ras.cProfile->link = (PProfile)0;
+ ras.cProfile->next = (PProfile)0;
+
+ if ( !ras.gProfile )
+ ras.gProfile = ras.cProfile;
+
+ ras.state = aState;
+ ras.fresh = TRUE;
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* End_Profile */
+ /* */
+ /* <Description> */
+ /* Finalizes the current profile. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
+ /* */
+ static
+ Bool End_Profile( RAS_ARG )
+ {
+ Long h;
+ PProfile oldProfile;
+
+
+ h = ras.top - ras.cProfile->offset;
+
+ if ( h < 0 )
+ {
+ FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+ ras.error = Raster_Err_Neg_Height;
+ return FAILURE;
+ }
+
+ if ( h > 0 )
+ {
+ FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+ (long)ras.cProfile, ras.cProfile->start, h ));
+
+ oldProfile = ras.cProfile;
+ ras.cProfile->height = h;
+ ras.cProfile = (PProfile)ras.top;
+
+ ras.top += AlignProfileSize;
+
+ ras.cProfile->height = 0;
+ ras.cProfile->offset = ras.top;
+ oldProfile->next = ras.cProfile;
+ ras.num_Profs++;
+ }
+
+ if ( ras.top >= ras.maxBuff )
+ {
+ FT_TRACE1(( "overflow in End_Profile\n" ));
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ ras.joint = FALSE;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Insert_Y_Turn */
+ /* */
+ /* <Description> */
+ /* Inserts a salient into the sorted list placed on top of the render */
+ /* pool. */
+ /* */
+ /* <Input> */
+ /* New y scanline position. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static
+ Bool Insert_Y_Turn( RAS_ARGS Int y )
+ {
+ PLong y_turns;
+ Int y2, n;
+
+
+ n = ras.numTurns - 1;
+ y_turns = ras.sizeBuff - ras.numTurns;
+
+ /* look for first y value that is <= */
+ while ( n >= 0 && y < y_turns[n] )
+ n--;
+
+ /* if it is <, simply insert it, ignore if == */
+ if ( n >= 0 && y > y_turns[n] )
+ while ( n >= 0 )
+ {
+ y2 = y_turns[n];
+ y_turns[n] = y;
+ y = y2;
+ n--;
+ }
+
+ if ( n < 0 )
+ {
+ if ( ras.maxBuff <= ras.top )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+ ras.maxBuff--;
+ ras.numTurns++;
+ ras.sizeBuff[-ras.numTurns] = y;
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Finalize_Profile_Table */
+ /* */
+ /* <Description> */
+ /* Adjusts all links in the profiles list. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success. FAILURE in case of overflow. */
+ /* */
+ static
+ Bool Finalize_Profile_Table( RAS_ARG )
+ {
+ Int bottom, top;
+ UShort n;
+ PProfile p;
+
+
+ n = ras.num_Profs;
+
+ if ( n > 1 )
+ {
+ p = ras.fProfile;
+ while ( n > 0 )
+ {
+ if ( n > 1 )
+ p->link = (PProfile)( p->offset + p->height );
+ else
+ p->link = NULL;
+
+ switch ( p->flow )
+ {
+ case Flow_Down:
+ bottom = p->start - p->height+1;
+ top = p->start;
+ p->start = bottom;
+ p->offset += p->height - 1;
+ break;
+
+ case Flow_Up:
+ default:
+ bottom = p->start;
+ top = p->start + p->height - 1;
+ }
+
+ if ( Insert_Y_Turn( RAS_VARS bottom ) ||
+ Insert_Y_Turn( RAS_VARS top + 1 ) )
+ return FAILURE;
+
+ p = p->link;
+ n--;
+ }
+ }
+ else
+ ras.fProfile = NULL;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Conic */
+ /* */
+ /* <Description> */
+ /* Subdivides one conic Bezier into two joint sub-arcs in the Bezier */
+ /* stack. */
+ /* */
+ /* <Input> */
+ /* None (subdivided Bezier is taken from the top of the stack). */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of this component. It is _the_ inner */
+ /* loop that should be optimized to hell to get the best performance. */
+ /* */
+ static
+ void Split_Conic( TPoint* base )
+ {
+ Long a, b;
+
+
+ base[4].x = base[2].x;
+ b = base[1].x;
+ a = base[3].x = ( base[2].x + b ) / 2;
+ b = base[1].x = ( base[0].x + b ) / 2;
+ base[2].x = ( a + b ) / 2;
+
+ base[4].y = base[2].y;
+ b = base[1].y;
+ a = base[3].y = ( base[2].y + b ) / 2;
+ b = base[1].y = ( base[0].y + b ) / 2;
+ base[2].y = ( a + b ) / 2;
+
+ /* hand optimized. gcc doesn't seem too good at common expression */
+ /* substitution and instruction scheduling ;-) */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Split_Cubic */
+ /* */
+ /* <Description> */
+ /* Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+ /* Bezier stack. */
+ /* */
+ /* <Note> */
+ /* This routine is the `beef' of the component. It is one of _the_ */
+ /* inner loops that should be optimized like hell to get the best */
+ /* performance. */
+ /* */
+ static
+ void Split_Cubic( TPoint* base )
+ {
+ Long a, b, c, d;
+
+
+ base[6].x = base[3].x;
+ c = base[1].x;
+ d = base[2].x;
+ base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+ base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].x = a = ( a + c + 1 ) >> 1;
+ base[4].x = b = ( b + c + 1 ) >> 1;
+ base[3].x = ( a + b + 1 ) >> 1;
+
+ base[6].y = base[3].y;
+ c = base[1].y;
+ d = base[2].y;
+ base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+ base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+ c = ( c + d + 1 ) >> 1;
+ base[2].y = a = ( a + c + 1 ) >> 1;
+ base[4].y = b = ( b + c + 1 ) >> 1;
+ base[3].y = ( a + b + 1 ) >> 1;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending line segment and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Line_Up( RAS_ARGS Long x1, Long y1,
+ Long x2, Long y2,
+ Long miny, Long maxy )
+ {
+ Long Dx, Dy;
+ Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
+ Long Ix, Rx, Ax;
+
+ PLong top;
+
+
+ Dx = x2 - x1;
+ Dy = y2 - y1;
+
+ if ( Dy <= 0 || y2 < miny || y1 > maxy )
+ return SUCCESS;
+
+ if ( y1 < miny )
+ {
+ /* Take care: miny-y1 can be a very large value; we use */
+ /* a slow MulDiv function to avoid clipping bugs */
+ x1 += SMulDiv( Dx, miny - y1, Dy );
+ e1 = TRUNC( miny );
+ f1 = 0;
+ }
+ else
+ {
+ e1 = TRUNC( y1 );
+ f1 = FRAC( y1 );
+ }
+
+ if ( y2 > maxy )
+ {
+ /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
+ e2 = TRUNC( maxy );
+ f2 = 0;
+ }
+ else
+ {
+ e2 = TRUNC( y2 );
+ f2 = FRAC( y2 );
+ }
+
+ if ( f1 > 0 )
+ {
+ if ( e1 == e2 )
+ return SUCCESS;
+ else
+ {
+ x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+ e1 += 1;
+ }
+ }
+ else
+ if ( ras.joint )
+ {
+ ras.top--;
+ ras.joint = FALSE;
+ }
+
+ ras.joint = ( f2 == 0 );
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = e1;
+ ras.fresh = FALSE;
+ }
+
+ size = e2 - e1 + 1;
+ if ( ras.top + size >= ras.maxBuff )
+ {
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ if ( Dx > 0 )
+ {
+ Ix = ( ras.precision * Dx ) / Dy;
+ Rx = ( ras.precision * Dx ) % Dy;
+ Dx = 1;
+ }
+ else
+ {
+ Ix = -( ( ras.precision * -Dx ) / Dy );
+ Rx = ( ras.precision * -Dx ) % Dy;
+ Dx = -1;
+ }
+
+ Ax = -Dy;
+ top = ras.top;
+
+ while ( size > 0 )
+ {
+ *top++ = x1;
+
+ x1 += Ix;
+ Ax += Rx;
+ if ( Ax >= 0 )
+ {
+ Ax -= Dy;
+ x1 += Dx;
+ }
+ size--;
+ }
+
+ ras.top = top;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending line segment and */
+ /* stores them in the render pool. */
+ /* */
+ /* <Input> */
+ /* x1 :: The x-coordinate of the segment's start point. */
+ /* */
+ /* y1 :: The y-coordinate of the segment's start point. */
+ /* */
+ /* x2 :: The x-coordinate of the segment's end point. */
+ /* */
+ /* y2 :: The y-coordinate of the segment's end point. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Line_Down( RAS_ARGS Long x1, Long y1,
+ Long x2, Long y2,
+ Long miny, Long maxy )
+ {
+ Bool result, fresh;
+
+
+ fresh = ras.fresh;
+
+ result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ return result;
+ }
+
+
+ /* A function type describing the functions used to split Bezier arcs */
+ typedef void (*TSplitter)( TPoint* base );
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Up */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an ascending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Bezier_Up( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ Long y1, y2, e, e2, e0;
+ Short f1;
+
+ TPoint* arc;
+ TPoint* start_arc;
+
+ PLong top;
+
+
+ arc = ras.arc;
+ y1 = arc[degree].y;
+ y2 = arc[0].y;
+ top = ras.top;
+
+ if ( y2 < miny || y1 > maxy )
+ goto Fin;
+
+ e2 = FLOOR( y2 );
+
+ if ( e2 > maxy )
+ e2 = maxy;
+
+ e0 = miny;
+
+ if ( y1 < miny )
+ e = miny;
+ else
+ {
+ e = CEILING( y1 );
+ f1 = FRAC( y1 );
+ e0 = e;
+
+ if ( f1 == 0 )
+ {
+ if ( ras.joint )
+ {
+ top--;
+ ras.joint = FALSE;
+ }
+
+ *top++ = arc[degree].x;
+
+ e += ras.precision;
+ }
+ }
+
+ if ( ras.fresh )
+ {
+ ras.cProfile->start = TRUNC( e0 );
+ ras.fresh = FALSE;
+ }
+
+ if ( e2 < e )
+ goto Fin;
+
+ if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+ {
+ ras.top = top;
+ ras.error = Raster_Err_Overflow;
+ return FAILURE;
+ }
+
+ start_arc = arc;
+
+ while ( arc >= start_arc && e <= e2 )
+ {
+ ras.joint = FALSE;
+
+ y2 = arc[0].y;
+
+ if ( y2 > e )
+ {
+ y1 = arc[degree].y;
+ if ( y2 - y1 >= ras.precision_step )
+ {
+ splitter( arc );
+ arc += degree;
+ }
+ else
+ {
+ *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+ e - y1, y2 - y1 );
+ arc -= degree;
+ e += ras.precision;
+ }
+ }
+ else
+ {
+ if ( y2 == e )
+ {
+ ras.joint = TRUE;
+ *top++ = arc[0].x;
+
+ e += ras.precision;
+ }
+ arc -= degree;
+ }
+ }
+
+ Fin:
+ ras.top = top;
+ ras.arc -= degree;
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Bezier_Down */
+ /* */
+ /* <Description> */
+ /* Computes the x-coordinates of an descending Bezier arc and stores */
+ /* them in the render pool. */
+ /* */
+ /* <Input> */
+ /* degree :: The degree of the Bezier arc (either 2 or 3). */
+ /* */
+ /* splitter :: The function to split Bezier arcs. */
+ /* */
+ /* miny :: A lower vertical clipping bound value. */
+ /* */
+ /* maxy :: An upper vertical clipping bound value. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow. */
+ /* */
+ static
+ Bool Bezier_Down( RAS_ARGS Int degree,
+ TSplitter splitter,
+ Long miny,
+ Long maxy )
+ {
+ TPoint* arc = ras.arc;
+ Bool result, fresh;
+
+
+ arc[0].y = -arc[0].y;
+ arc[1].y = -arc[1].y;
+ arc[2].y = -arc[2].y;
+ if ( degree > 2 )
+ arc[3].y = -arc[3].y;
+
+ fresh = ras.fresh;
+
+ result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+ if ( fresh && !ras.fresh )
+ ras.cProfile->start = -ras.cProfile->start;
+
+ arc[0].y = -arc[0].y;
+ return result;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Line_To */
+ /* */
+ /* <Description> */
+ /* Injects a new line segment and adjusts Profiles list. */
+ /* */
+ /* <Input> */
+ /* x :: The x-coordinate of the segment's end point (its start point */
+ /* is stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the segment's end point (its start point */
+ /* is stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Line_To( RAS_ARGS Long x,
+ Long y )
+ {
+ /* First, detect a change of direction */
+
+ switch ( ras.state )
+ {
+ case Unknown:
+ if ( y > ras.lastY )
+ {
+ if ( New_Profile( RAS_VARS Ascending ) )
+ return FAILURE;
+ }
+ else
+ {
+ if ( y < ras.lastY )
+ if ( New_Profile( RAS_VARS Descending ) )
+ return FAILURE;
+ }
+ break;
+
+ case Ascending:
+ if ( y < ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Descending ) )
+ return FAILURE;
+ }
+ break;
+
+ case Descending:
+ if ( y > ras.lastY )
+ {
+ if ( End_Profile( RAS_VAR ) ||
+ New_Profile( RAS_VARS Ascending ) )
+ return FAILURE;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ /* Then compute the lines */
+
+ switch ( ras.state )
+ {
+ case Ascending:
+ if ( Line_Up ( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ case Descending:
+ if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+ x, y, ras.minY, ras.maxY ) )
+ return FAILURE;
+ break;
+
+ default:
+ ;
+ }
+
+ ras.lastX = x;
+ ras.lastY = y;
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Conic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new conic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx :: The x-coordinate of the arc's new control point. */
+ /* */
+ /* cy :: The y-coordinate of the arc's new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Conic_To( RAS_ARGS Long cx,
+ Long cy,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, x3, ymin, ymax;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[2].x = ras.lastX;
+ ras.arc[2].y = ras.lastY;
+ ras.arc[1].x = cx; ras.arc[1].y = cy;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[2].y;
+ y2 = ras.arc[1].y;
+ y3 = ras.arc[0].y;
+ x3 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y3 )
+ {
+ ymin = y1;
+ ymax = y3;
+ }
+ else
+ {
+ ymin = y3;
+ ymax = y1;
+ }
+
+ if ( y2 < ymin || y2 > ymax )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Conic( ras.arc );
+ ras.arc += 2;
+ }
+ else if ( y1 == y3 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 2;
+ }
+ else
+ {
+ /* the arc is y-monotonous, either ascending or descending */
+ /* detect a change of direction */
+ state_bez = y1 < y3 ? Ascending : Descending;
+ if ( ras.state != state_bez )
+ {
+ /* finalize current profile if any */
+ if ( ras.state != Unknown &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ /* create a new profile */
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* now call the appropriate routine */
+ if ( state_bez == Ascending )
+ {
+ if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x3;
+ ras.lastY = y3;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Cubic_To */
+ /* */
+ /* <Description> */
+ /* Injects a new cubic arc and adjusts the profile list. */
+ /* */
+ /* <Input> */
+ /* cx1 :: The x-coordinate of the arc's first new control point. */
+ /* */
+ /* cy1 :: The y-coordinate of the arc's first new control point. */
+ /* */
+ /* cx2 :: The x-coordinate of the arc's second new control point. */
+ /* */
+ /* cy2 :: The y-coordinate of the arc's second new control point. */
+ /* */
+ /* x :: The x-coordinate of the arc's end point (its start point is */
+ /* stored in `LastX'). */
+ /* */
+ /* y :: The y-coordinate of the arc's end point (its start point is */
+ /* stored in `LastY'). */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
+ /* profile. */
+ /* */
+ static
+ Bool Cubic_To( RAS_ARGS Long cx1,
+ Long cy1,
+ Long cx2,
+ Long cy2,
+ Long x,
+ Long y )
+ {
+ Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+ TStates state_bez;
+
+
+ ras.arc = ras.arcs;
+ ras.arc[3].x = ras.lastX;
+ ras.arc[3].y = ras.lastY;
+ ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+ ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+ ras.arc[0].x = x; ras.arc[0].y = y;
+
+ do
+ {
+ y1 = ras.arc[3].y;
+ y2 = ras.arc[2].y;
+ y3 = ras.arc[1].y;
+ y4 = ras.arc[0].y;
+ x4 = ras.arc[0].x;
+
+ /* first, categorize the Bezier arc */
+
+ if ( y1 <= y4 )
+ {
+ ymin1 = y1;
+ ymax1 = y4;
+ }
+ else
+ {
+ ymin1 = y4;
+ ymax1 = y1;
+ }
+
+ if ( y2 <= y3 )
+ {
+ ymin2 = y2;
+ ymax2 = y3;
+ }
+ else
+ {
+ ymin2 = y3;
+ ymax2 = y2;
+ }
+
+ if ( ymin2 < ymin1 || ymax2 > ymax1 )
+ {
+ /* this arc has no given direction, split it! */
+ Split_Cubic( ras.arc );
+ ras.arc += 3;
+ }
+ else if ( y1 == y4 )
+ {
+ /* this arc is flat, ignore it and pop it from the Bezier stack */
+ ras.arc -= 3;
+ }
+ else
+ {
+ state_bez = y1 <= y4 ? Ascending : Descending;
+
+ /* detect a change of direction */
+ if ( ras.state != state_bez )
+ {
+ if ( ras.state != Unknown &&
+ End_Profile( RAS_VAR ) )
+ goto Fail;
+
+ if ( New_Profile( RAS_VARS state_bez ) )
+ goto Fail;
+ }
+
+ /* compute intersections */
+ if ( state_bez == Ascending )
+ {
+ if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+ else
+ if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+ goto Fail;
+ }
+
+ } while ( ras.arc >= ras.arcs );
+
+ ras.lastX = x4;
+ ras.lastY = y4;
+
+ return SUCCESS;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+#undef SWAP_
+#define SWAP_( x, y ) do \
+ { \
+ Long swap = x; \
+ \
+ \
+ x = y; \
+ y = swap; \
+ } while ( 0 )
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Decompose_Curve */
+ /* */
+ /* <Description> */
+ /* Scans the outline arays in order to emit individual segments and */
+ /* Beziers by calling Line_To() and Bezier_To(). It handles all */
+ /* weird cases, like when the first point is off the curve, or when */
+ /* there are simply no `on' points in the contour! */
+ /* */
+ /* <Input> */
+ /* first :: The index of the first point in the contour. */
+ /* */
+ /* last :: The index of the last point in the contour. */
+ /* */
+ /* flipped :: If set, flip the direction of the curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE on error. */
+ /* */
+ static
+ Bool Decompose_Curve( RAS_ARGS UShort first,
+ UShort last,
+ int flipped )
+ {
+ FT_Vector v_last;
+ FT_Vector v_control;
+ FT_Vector v_start;
+
+ FT_Vector* points;
+ FT_Vector* point;
+ FT_Vector* limit;
+ char* tags;
+
+ char tag; /* current point's state */
+
+
+ points = ras.outline.points;
+ limit = points + last;
+
+ v_start.x = SCALED( points[first].x );
+ v_start.y = SCALED( points[first].y );
+ v_last.x = SCALED( points[last].x );
+ v_last.y = SCALED( points[last].y );
+
+ if ( flipped )
+ {
+ SWAP_( v_start.x, v_start.y );
+ SWAP_( v_last.x, v_last.y );
+ }
+
+ v_control = v_start;
+
+ point = points + first;
+ tags = ras.outline.tags + first;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ /* A contour cannot start with a cubic control point! */
+ if ( tag == FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ /* check first point to determine origin */
+ if ( tag == FT_Curve_Tag_Conic )
+ {
+ /* first point is conic control. Yes, this happens. */
+ if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_Curve_Tag_On )
+ {
+ /* start at last point if it is on the curve */
+ v_start = v_last;
+ limit--;
+ }
+ else
+ {
+ /* if both first and last points are conic, */
+ /* start at their middle and record its position */
+ /* for closure */
+ v_start.x = ( v_start.x + v_last.x ) / 2;
+ v_start.y = ( v_start.y + v_last.y ) / 2;
+
+ v_last = v_start;
+ }
+ point--;
+ tags--;
+ }
+
+ ras.lastX = v_start.x;
+ ras.lastY = v_start.y;
+
+ while ( point < limit )
+ {
+ point++;
+ tags++;
+
+ tag = FT_CURVE_TAG( tags[0] );
+
+ switch ( tag )
+ {
+ case FT_Curve_Tag_On: /* emit a single line_to */
+ {
+ Long x, y;
+
+
+ x = SCALED( point->x );
+ y = SCALED( point->y );
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( Line_To( RAS_VARS x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ case FT_Curve_Tag_Conic: /* consume conic arcs */
+ {
+ v_control.x = SCALED( point[0].x );
+ v_control.y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( v_control.x, v_control.y );
+
+ Do_Conic:
+ if ( point < limit )
+ {
+ FT_Vector v_middle;
+ Long x, y;
+
+
+ point++;
+ tags++;
+ tag = FT_CURVE_TAG( tags[0] );
+
+ x = SCALED( point[0].x );
+ y = SCALED( point[0].y );
+
+ if ( flipped )
+ SWAP_( x, y );
+
+ if ( tag == FT_Curve_Tag_On )
+ {
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( tag != FT_Curve_Tag_Conic )
+ goto Invalid_Outline;
+
+ v_middle.x = ( v_control.x + x ) / 2;
+ v_middle.y = ( v_control.y + y ) / 2;
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_middle.x, v_middle.y ) )
+ goto Fail;
+
+ v_control.x = x;
+ v_control.y = y;
+
+ goto Do_Conic;
+ }
+
+ if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+ v_start.x, v_start.y ) )
+ goto Fail;
+
+ goto Close;
+ }
+
+ default: /* FT_Curve_Tag_Cubic */
+ {
+ Long x1, y1, x2, y2, x3, y3;
+
+
+ if ( point + 1 > limit ||
+ FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
+ goto Invalid_Outline;
+
+ point += 2;
+ tags += 2;
+
+ x1 = SCALED( point[-2].x );
+ y1 = SCALED( point[-2].y );
+ x2 = SCALED( point[-1].x );
+ y2 = SCALED( point[-1].y );
+ x3 = SCALED( point[ 0].x );
+ y3 = SCALED( point[ 0].y );
+
+ if ( flipped )
+ {
+ SWAP_( x1, y1 );
+ SWAP_( x2, y2 );
+ SWAP_( x3, y3 );
+ }
+
+ if ( point <= limit )
+ {
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+ goto Fail;
+ continue;
+ }
+
+ if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+ goto Fail;
+ goto Close;
+ }
+ }
+ }
+
+ /* close the contour with a line segment */
+ if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+ goto Fail;
+
+ Close:
+ return SUCCESS;
+
+ Invalid_Outline:
+ ras.error = Raster_Err_Invalid;
+
+ Fail:
+ return FAILURE;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Convert_Glyph */
+ /* */
+ /* <Description> */
+ /* Converts a glyph into a series of segments and arcs and makes a */
+ /* profiles list with them. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of curve. */
+ /* */
+ /* <Return> */
+ /* SUCCESS on success, FAILURE if any error was encountered during */
+ /* rendering. */
+ /* */
+ static
+ Bool Convert_Glyph( RAS_ARGS int flipped )
+ {
+ Short i;
+ UShort start;
+
+ PProfile lastProfile;
+
+
+ ras.fProfile = NULL;
+ ras.joint = FALSE;
+ ras.fresh = FALSE;
+
+ ras.maxBuff = ras.sizeBuff - AlignProfileSize;
+
+ ras.numTurns = 0;
+
+ ras.cProfile = (PProfile)ras.top;
+ ras.cProfile->offset = ras.top;
+ ras.num_Profs = 0;
+
+ start = 0;
+
+ for ( i = 0; i < ras.outline.n_contours; i++ )
+ {
+ ras.state = Unknown;
+ ras.gProfile = NULL;
+
+ if ( Decompose_Curve( RAS_VARS start, ras.outline.contours[i], flipped ) )
+ return FAILURE;
+
+ start = ras.outline.contours[i] + 1;
+
+ /* We must now see whether the extreme arcs join or not */
+ if ( FRAC( ras.lastY ) == 0 &&
+ ras.lastY >= ras.minY &&
+ ras.lastY <= ras.maxY )
+ if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+ ras.top--;
+ /* Note that ras.gProfile can be nil if the contour was too small */
+ /* to be drawn. */
+
+ lastProfile = ras.cProfile;
+ if ( End_Profile( RAS_VAR ) )
+ return FAILURE;
+
+ /* close the `next profile in contour' linked list */
+ if ( ras.gProfile )
+ lastProfile->next = ras.gProfile;
+ }
+
+ if ( Finalize_Profile_Table( RAS_VAR ) )
+ return FAILURE;
+
+ return ( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+ }
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /** **/
+ /** SCAN-LINE SWEEPS AND DRAWING **/
+ /** **/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* Init_Linked */
+ /* */
+ /* Initializes an empty linked list. */
+ /* */
+ static
+ void Init_Linked( TProfileList* l )
+ {
+ *l = NULL;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* InsNew */
+ /* */
+ /* Inserts a new profile in a linked list. */
+ /* */
+ static
+ void InsNew( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+ Long x;
+
+
+ old = list;
+ current = *old;
+ x = profile->X;
+
+ while ( current )
+ {
+ if ( x < current->X )
+ break;
+ old = ¤t->link;
+ current = *old;
+ }
+
+ profile->link = current;
+ *old = profile;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* DelOld */
+ /* */
+ /* Removes an old profile from a linked list. */
+ /* */
+ static
+ void DelOld( PProfileList list,
+ PProfile profile )
+ {
+ PProfile *old, current;
+
+
+ old = list;
+ current = *old;
+
+ while ( current )
+ {
+ if ( current == profile )
+ {
+ *old = current->link;
+ return;
+ }
+
+ old = ¤t->link;
+ current = *old;
+ }
+
+ /* we should never get there, unless the profile was not part of */
+ /* the list. */
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Update */
+ /* */
+ /* Update all X offsets of a drawing list. */
+ /* */
+ static
+ void Update( PProfile first )
+ {
+ PProfile current = first;
+
+
+ while ( current )
+ {
+ current->X = *current->offset;
+ current->offset += current->flow;
+ current->height--;
+ current = current->link;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Sort */
+ /* */
+ /* Sorts a trace list. In 95%, the list is already sorted. We need */
+ /* an algorithm which is fast in this case. Bubble sort is enough */
+ /* and simple. */
+ /* */
+ static
+ void Sort( PProfileList list )
+ {
+ PProfile *old, current, next;
+
+
+ /* First, set the new X coordinate of each profile */
+ Update( *list );
+
+ /* Then sort them */
+ old = list;
+ current = *old;
+
+ if ( !current )
+ return;
+
+ next = current->link;
+
+ while ( next )
+ {
+ if ( current->X <= next->X )
+ {
+ old = ¤t->link;
+ current = *old;
+
+ if ( !current )
+ return;
+ }
+ else
+ {
+ *old = next;
+ current->link = next->link;
+ next->link = current;
+
+ old = list;
+ current = *old;
+ }
+
+ next = current->link;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the vertical black/white */
+ /* sweep phase by the generic Draw_Sweep() function. */
+ /* */
+ /*************************************************************************/
+
+ static
+ void Vertical_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch = ras.target.pitch;
+
+ UNUSED( max );
+
+
+ ras.traceIncr = (Short)-pitch;
+ ras.traceOfs = -*min * pitch;
+ if ( pitch > 0 )
+ ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+ ras.gray_min_x = 0;
+ ras.gray_max_x = 0;
+ }
+
+
+ static
+ void Vertical_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ Short c1, c2;
+ Byte f1, f2;
+ Byte* target;
+
+ UNUSED( y );
+ UNUSED( left );
+ UNUSED( right );
+
+
+ /* Drop-out control */
+
+ e1 = TRUNC( CEILING( x1 ) );
+
+ if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+ e2 = e1;
+ else
+ e2 = TRUNC( FLOOR( x2 ) );
+
+ if ( e2 >= 0 && e1 < ras.bWidth )
+ {
+ if ( e1 < 0 ) e1 = 0;
+ if ( e2 >= ras.bWidth ) e2 = ras.bWidth - 1;
+
+ c1 = (Short)( e1 >> 3 );
+ c2 = (Short)( e2 >> 3 );
+
+ f1 = (unsigned char)0xFF >> ( e1 & 7 );
+ f2 = ~((unsigned char)0x7F >> ( e2 & 7 ));
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c2 ) ras.gray_max_x = c2;
+
+ target = ras.bTarget + ras.traceOfs + c1;
+ c2 -= c1;
+
+ if ( c2 > 0 )
+ {
+ target[0] |= f1;
+
+ /* memset() is slower than the following code on many platforms. */
+ /* This is due to the fact that, in the vast majority of cases, */
+ /* the span length in bytes is relatively small. */
+ c2--;
+ while ( c2 > 0 )
+ {
+ *(++target) = 0xFF;
+ c2--;
+ }
+ target[1] |= f2;
+ }
+ else
+ *target |= ( f1 & f2 );
+ }
+ }
+
+
+ static
+ void Vertical_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ Short c1, f1;
+
+
+ /* Drop-out control */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( (x1 + x2 + 1) / 2 );
+ break;
+
+ case 2:
+ case 5:
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+ /* Here, we only get rid of stubs recognized if: */
+ /* */
+ /* upper stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Right is the successor of P_Left in that contour */
+ /* - y is the top of P_Left and P_Right */
+ /* */
+ /* lower stub: */
+ /* */
+ /* - P_Left and P_Right are in the same contour */
+ /* - P_Left is the successor of P_Right in that contour */
+ /* - y is the bottom of P_Left */
+ /* */
+
+ /* FIXXXME: uncommenting this line solves the disappearing */
+ /* bit problem in the `7' of verdana 10pts, but */
+ /* makes a new one in the `C' of arial 14pts */
+
+#if 0
+ if ( x2 - x1 < ras.precision_half )
+#endif
+ {
+ /* upper stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* lower stub test */
+ if ( right->next == left && left->start == y )
+ return;
+ }
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ c1 = (Short)( e1 >> 3 );
+ f1 = e1 & 7;
+
+ if ( e1 >= 0 && e1 < ras.bWidth &&
+ ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.bWidth )
+ {
+ c1 = (Short)( e1 >> 3 );
+ f1 = e1 & 7;
+
+ if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+ if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+ ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+ }
+ }
+
+
+ static
+ void Vertical_Sweep_Step( RAS_ARG )
+ {
+ ras.traceOfs += ras.traceIncr;
+ }
+
+
+ /***********************************************************************/
+ /* */
+ /* Horizontal Sweep Procedure Set */
+ /* */
+ /* These four routines are used during the horizontal black/white */
+ /* sweep phase by the generic Draw_Sweep() function. */
+ /* */
+ /***********************************************************************/
+
+ static
+ void Horizontal_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ /* nothing, really */
+ UNUSED( raster );
+ UNUSED( min );
+ UNUSED( max );
+ }
+
+
+ static
+ void Horizontal_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+ UNUSED( left );
+ UNUSED( right );
+
+
+ if ( x2 - x1 < ras.precision )
+ {
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 == e2 )
+ {
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ PByte p;
+
+
+ p = bits - e1*ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ p[0] |= f1;
+ }
+ }
+ }
+ }
+
+
+ static
+ void Horizontal_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte bits;
+ Byte f1;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ /* check that the rightmost pixel isn't set */
+
+ e1 = TRUNC( e1 );
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( e1 >= 0 &&
+ e1 < ras.target.rows &&
+ *bits & f1 )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ bits = ras.bTarget + ( y >> 3 );
+ f1 = (Byte)( 0x80 >> ( y & 7 ) );
+
+ e1 = TRUNC( e1 );
+
+ if ( e1 >= 0 && e1 < ras.target.rows )
+ {
+ bits -= e1 * ras.target.pitch;
+ if ( ras.target.pitch > 0 )
+ bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ bits[0] |= f1;
+ }
+ }
+
+
+ static
+ void Horizontal_Sweep_Step( RAS_ARG )
+ {
+ /* Nothing, really */
+ UNUSED( raster );
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* Vertical Gray Sweep Procedure Set */
+ /* */
+ /* These two routines are used during the vertical gray-levels sweep */
+ /* phase by the generic Draw_Sweep() function. */
+ /* */
+ /* NOTES */
+ /* */
+ /* - The target pixmap's width *must* be a multiple of 4. */
+ /* */
+ /* - You have to use the function Vertical_Sweep_Span() for the gray */
+ /* span call. */
+ /* */
+ /*************************************************************************/
+
+ static
+ void Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
+ Short* max )
+ {
+ Long pitch, byte_len;
+
+
+ *min = *min & -2;
+ *max = ( *max + 3 ) & -2;
+
+ ras.traceOfs = 0;
+ pitch = ras.target.pitch;
+ byte_len = -pitch;
+ ras.traceIncr = (Short)byte_len;
+ ras.traceG = ( *min / 2 ) * byte_len;
+
+ if ( pitch > 0 )
+ {
+ ras.traceG += ( ras.target.rows - 1 ) * pitch;
+ byte_len = -byte_len;
+ }
+
+ ras.gray_min_x = (Short)byte_len;
+ ras.gray_max_x = -(Short)byte_len;
+ }
+
+
+ static
+ void Vertical_Gray_Sweep_Step( RAS_ARG )
+ {
+ Int c1, c2;
+ PByte pix, bit, bit2;
+ Int* count = ras.count_table;
+ Byte* grays;
+
+
+ ras.traceOfs += ras.gray_width;
+
+ if ( ras.traceOfs > ras.gray_width )
+ {
+ pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+ grays = ras.grays;
+
+ if ( ras.gray_max_x >= 0 )
+ {
+ Long last_pixel = ras.target.width - 1;
+ Int last_cell = last_pixel >> 2;
+ Int last_bit = last_pixel & 3;
+ Bool over = 0;
+
+ if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+ {
+ ras.gray_max_x = last_cell - 1;
+ over = 1;
+ }
+
+ if ( ras.gray_min_x < 0 )
+ ras.gray_min_x = 0;
+
+ bit = ras.bTarget + ras.gray_min_x;
+ bit2 = bit + ras.gray_width;
+
+ c1 = ras.gray_max_x - ras.gray_min_x;
+
+ while ( c1 >= 0 )
+ {
+ c2 = count[*bit] + count[*bit2];
+
+ if ( c2 )
+ {
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ pix[3] = grays[ c2 & 0x000F];
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+
+ bit++;
+ bit2++;
+ pix += 4;
+ c1--;
+ }
+
+ if ( over )
+ {
+ c2 = count[*bit] + count[*bit2];
+ if ( c2 )
+ {
+ switch ( last_bit )
+ {
+ case 2:
+ pix[2] = grays[(c2 >> 4 ) & 0x000F];
+ case 1:
+ pix[1] = grays[(c2 >> 8 ) & 0x000F];
+ default:
+ pix[0] = grays[(c2 >> 12) & 0x000F];
+ }
+
+ *bit = 0;
+ *bit2 = 0;
+ }
+ }
+ }
+
+ ras.traceOfs = 0;
+ ras.traceG += ras.traceIncr;
+
+ ras.gray_min_x = 32000;
+ ras.gray_max_x = -32000;
+ }
+ }
+
+
+ static
+ void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ /* nothing, really */
+ UNUSED( raster );
+ UNUSED( y );
+ UNUSED( x1 );
+ UNUSED( x2 );
+ UNUSED( left );
+ UNUSED( right );
+ }
+
+
+ static
+ void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
+ FT_F26Dot6 x1,
+ FT_F26Dot6 x2,
+ PProfile left,
+ PProfile right )
+ {
+ Long e1, e2;
+ PByte pixel;
+ Byte color;
+
+
+ /* During the horizontal sweep, we only take care of drop-outs */
+ e1 = CEILING( x1 );
+ e2 = FLOOR ( x2 );
+
+ if ( e1 > e2 )
+ {
+ if ( e1 == e2 + ras.precision )
+ {
+ switch ( ras.dropOutControl )
+ {
+ case 1:
+ e1 = e2;
+ break;
+
+ case 4:
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+ break;
+
+ case 2:
+ case 5:
+
+ /* Drop-out Control Rule #4 */
+
+ /* The spec is not very clear regarding rule #4. It */
+ /* presents a method that is way too costly to implement */
+ /* while the general idea seems to get rid of `stubs'. */
+ /* */
+
+ /* rightmost stub test */
+ if ( left->next == right && left->height <= 0 )
+ return;
+
+ /* leftmost stub test */
+ if ( right->next == left && left->start == y )
+ return;
+
+ if ( ras.dropOutControl == 2 )
+ e1 = e2;
+ else
+ e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+ break;
+
+ default:
+ return; /* unsupported mode */
+ }
+ }
+ else
+ return;
+ }
+
+ if ( e1 >= 0 )
+ {
+ if ( x2 - x1 >= ras.precision_half )
+ color = ras.grays[2];
+ else
+ color = ras.grays[1];
+
+ e1 = TRUNC( e1 ) / 2;
+ if ( e1 < ras.target.rows )
+ {
+ pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+ if ( ras.target.pitch > 0 )
+ pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+ if ( pixel[0] == ras.grays[0] )
+ pixel[0] = color;
+ }
+ }
+ }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+ /*************************************************************************/
+ /* */
+ /* Generic Sweep Drawing routine */
+ /* */
+ /*************************************************************************/
+
+ static
+ Bool Draw_Sweep( RAS_ARG )
+ {
+ Short y, y_change, y_height;
+
+ PProfile P, Q, P_Left, P_Right;
+
+ Short min_Y, max_Y, top, bottom, dropouts;
+
+ Long x1, x2, xs, e1, e2;
+
+ TProfileList wait;
+ TProfileList draw_left, draw_right;
+
+
+ /* Init empty linked lists */
+
+ Init_Linked( &wait );
+
+ Init_Linked( &draw_left );
+ Init_Linked( &draw_right );
+
+ /* first, compute min and max Y */
+
+ P = ras.fProfile;
+ max_Y = (short)TRUNC( ras.minY );
+ min_Y = (short)TRUNC( ras.maxY );
+
+ while ( P )
+ {
+ Q = P->link;
+
+ bottom = (Short)P->start;
+ top = (Short)P->start + P->height - 1;
+
+ if ( min_Y > bottom ) min_Y = bottom;
+ if ( max_Y < top ) max_Y = top;
+
+ P->X = 0;
+ InsNew( &wait, P );
+
+ P = Q;
+ }
+
+ /* Check the Y-turns */
+ if ( ras.numTurns == 0 )
+ {
+ ras.error = Raster_Err_Invalid;
+ return FAILURE;
+ }
+
+ /* Now inits the sweep */
+
+ ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+ /* Then compute the distance of each profile from min_Y */
+
+ P = wait;
+
+ while ( P )
+ {
+ P->countL = P->start - min_Y;
+ P = P->link;
+ }
+
+ /* Let's go */
+
+ y = min_Y;
+ y_height = 0;
+
+ if ( ras.numTurns > 0 &&
+ ras.sizeBuff[-ras.numTurns] == min_Y )
+ ras.numTurns--;
+
+ while ( ras.numTurns > 0 )
+ {
+ /* look in the wait list for new activations */
+
+ P = wait;
+
+ while ( P )
+ {
+ Q = P->link;
+ P->countL -= y_height;
+ if ( P->countL == 0 )
+ {
+ DelOld( &wait, P );
+
+ switch ( P->flow )
+ {
+ case Flow_Up:
+ InsNew( &draw_left, P );
+ break;
+
+ case Flow_Down:
+ InsNew( &draw_right, P );
+ break;
+ }
+ }
+
+ P = Q;
+ }
+
+ /* Sort the drawing lists */
+
+ Sort( &draw_left );
+ Sort( &draw_right );
+
+ y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+ y_height = y_change - y;
+
+ while ( y < y_change )
+ {
+ /* Let's trace */
+
+ dropouts = 0;
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ x1 = P_Left ->X;
+ x2 = P_Right->X;
+
+ if ( x1 > x2 )
+ {
+ xs = x1;
+ x1 = x2;
+ x2 = xs;
+ }
+
+ if ( x2 - x1 <= ras.precision )
+ {
+ e1 = FLOOR( x1 );
+ e2 = CEILING( x2 );
+
+ if ( ras.dropOutControl != 0 &&
+ ( e1 > e2 || e2 == e1 + ras.precision ) )
+ {
+ /* a drop out was detected */
+
+ P_Left ->X = x1;
+ P_Right->X = x2;
+
+ /* mark profile for drop-out processing */
+ P_Left->countL = 1;
+ dropouts++;
+
+ goto Skip_To_Next;
+ }
+ }
+
+ ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+ Skip_To_Next:
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ /* now perform the dropouts _after_ the span drawing */
+ /* drop-outs processing has been moved out of the loop */
+ /* for performance tuning */
+ if ( dropouts > 0 )
+ goto Scan_DropOuts;
+
+ Next_Line:
+
+ ras.Proc_Sweep_Step( RAS_VAR );
+
+ y++;
+
+ if ( y < y_change )
+ {
+ Sort( &draw_left );
+ Sort( &draw_right );
+ }
+ }
+
+ /* Now finalize the profiles that needs it */
+
+ {
+ PProfile Q, P;
+
+
+ P = draw_left;
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_left, P );
+ P = Q;
+ }
+ }
+
+ {
+ PProfile Q, P = draw_right;
+
+
+ while ( P )
+ {
+ Q = P->link;
+ if ( P->height == 0 )
+ DelOld( &draw_right, P );
+ P = Q;
+ }
+ }
+ }
+
+ /* for gray-scaling, flushes the bitmap scanline cache */
+ while ( y <= max_Y )
+ {
+ ras.Proc_Sweep_Step( RAS_VAR );
+ y++;
+ }
+
+ return SUCCESS;
+
+ Scan_DropOuts:
+
+ P_Left = draw_left;
+ P_Right = draw_right;
+
+ while ( P_Left )
+ {
+ if ( P_Left->countL )
+ {
+ P_Left->countL = 0;
+#if 0
+ dropouts--; /* -- this is useful when debugging only */
+#endif
+ ras.Proc_Sweep_Drop( RAS_VARS y,
+ P_Left->X,
+ P_Right->X,
+ P_Left,
+ P_Right );
+ }
+
+ P_Left = P_Left->link;
+ P_Right = P_Right->link;
+ }
+
+ goto Next_Line;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Single_Pass */
+ /* */
+ /* <Description> */
+ /* Performs one sweep with sub-banding. */
+ /* */
+ /* <Input> */
+ /* flipped :: If set, flip the direction of the outline. */
+ /* */
+ /* <Return> */
+ /* Renderer error code. */
+ /* */
+ static
+ int Render_Single_Pass( RAS_ARGS Bool flipped )
+ {
+ Short i, j, k;
+
+
+ while ( ras.band_top >= 0 )
+ {
+ ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+ ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+ ras.top = ras.buff;
+
+ ras.error = Raster_Err_None;
+
+ if ( Convert_Glyph( RAS_VARS flipped ) )
+ {
+ if ( ras.error != Raster_Err_Overflow )
+ return FAILURE;
+
+ ras.error = Raster_Err_None;
+
+ /* sub-banding */
+
+#ifdef DEBUG_RASTER
+ ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+ i = ras.band_stack[ras.band_top].y_min;
+ j = ras.band_stack[ras.band_top].y_max;
+
+ k = ( i + j ) / 2;
+
+ if ( ras.band_top >= 7 || k < i )
+ {
+ ras.band_top = 0;
+ ras.error = Raster_Err_Invalid;
+
+ return ras.error;
+ }
+
+ ras.band_stack[ras.band_top + 1].y_min = k;
+ ras.band_stack[ras.band_top + 1].y_max = j;
+
+ ras.band_stack[ras.band_top].y_max = k - 1;
+
+ ras.band_top++;
+ }
+ else
+ {
+ if ( ras.fProfile )
+ if ( Draw_Sweep( RAS_VAR ) )
+ return ras.error;
+ ras.band_top--;
+ }
+ }
+
+ return SUCCESS;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph in a bitmap. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* XXX Fixme: ftraster's error codes don't harmonize with FT2's ones! */
+ /* */
+ LOCAL_FUNC
+ FT_Error Render_Glyph( RAS_ARG )
+ {
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ ft_outline_high_precision );
+ ras.scale_shift = ras.precision_shift;
+ ras.dropOutControl = 2;
+ ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
+
+ /* Vertical Sweep */
+ ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.rows - 1;
+
+ ras.bWidth = ras.target.width;
+ ras.bTarget = (Byte*)ras.target.buffer;
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.width - 1;
+
+ if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+ return error;
+ }
+
+ return FT_Err_Ok;
+ }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Render_Gray_Glyph */
+ /* */
+ /* <Description> */
+ /* Renders a glyph with grayscaling. Sub-banding if needed. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error Render_Gray_Glyph( RAS_ARG )
+ {
+ Long pixel_width;
+ FT_Error error;
+
+
+ Set_High_Precision( RAS_VARS ras.outline.flags &
+ ft_outline_high_precision );
+ ras.scale_shift = ras.precision_shift + 1;
+ ras.dropOutControl = 2;
+ ras.second_pass = !( ras.outline.flags & ft_outline_single_pass );
+
+
+ /* Vertical Sweep */
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+ ras.bWidth = ras.gray_width;
+ pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+ if ( ras.bWidth > pixel_width )
+ ras.bWidth = pixel_width;
+
+ ras.bWidth = ras.bWidth * 8;
+ ras.bTarget = (Byte*)ras.gray_lines;
+ ras.gTarget = (Byte*)ras.target.buffer;
+
+ ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+ ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+ ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+ ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+ error = Render_Single_Pass( RAS_VARS 0 );
+ if (error)
+ return error;
+
+ /* Horizontal Sweep */
+ if ( ras.second_pass && ras.dropOutControl != 0 )
+ {
+ ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+ ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+ ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+ ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+ ras.band_top = 0;
+ ras.band_stack[0].y_min = 0;
+ ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+ error = Render_Single_Pass( RAS_VARS 1 );
+ if (error)
+ return error;
+ }
+
+ return FT_Err_Ok;
+ }
+
+#else /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+ LOCAL_FUNC
+ FT_Error Render_Gray_Glyph( RAS_ARG )
+ {
+ UNUSED_RASTER;
+ return Raster_Err_Unsupported;
+ }
+
+#endif
+
+
+ static
+ void ft_black_init( TRaster_Instance* raster )
+ {
+ FT_UInt n;
+ FT_ULong c;
+
+ /* setup count table */
+ for ( n = 0; n < 256; n++ )
+ {
+ c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
+
+ c = ( ( c << 6 ) & 0x3000 ) |
+ ( ( c << 4 ) & 0x0300 ) |
+ ( ( c << 2 ) & 0x0030 ) |
+ (c & 0x0003 );
+
+ raster->count_table[n] = c;
+ }
+
+ /* set default 5-levels gray palette */
+ for ( n = 0; n < 5; n++ )
+ raster->grays[n] = n * 255 / 4;
+
+ raster->gray_width = RASTER_GRAY_LINES / 2;
+ }
+
+ /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+ /**** a static object. *****/
+
+#ifdef _STANDALONE_
+
+
+ static
+ int ft_black_new( void* memory,
+ FT_Raster *araster )
+ {
+ static FT_RasterRec_ the_raster;
+
+
+ *araster = &the_raster;
+ memset( &the_raster, sizeof ( the_raster ), 0 );
+ ft_black_init( &the_raster );
+
+ return 0;
+ }
+
+
+ static
+ void ft_black_done( FT_Raster raster )
+ {
+ /* nothing */
+ raster->init = 0;
+ }
+
+
+#else /* _STANDALONE_ */
+
+
+ static
+ int ft_black_new( FT_Memory memory,
+ TRaster_Instance** araster )
+ {
+ FT_Error error;
+ TRaster_Instance* raster;
+
+
+ *araster = 0;
+ if ( !ALLOC( raster, sizeof ( *raster ) ) )
+ {
+ raster->memory = memory;
+ ft_black_init( raster );
+
+ *araster = raster;
+ }
+
+ return error;
+ }
+
+
+ static
+ void ft_black_done( TRaster_Instance* raster )
+ {
+ FT_Memory memory = (FT_Memory)raster->memory;
+ FREE( raster );
+ }
+
+
+#endif /* _STANDALONE_ */
+
+
+ static
+ void ft_black_reset( TRaster_Instance* raster,
+ const char* pool_base,
+ long pool_size )
+ {
+ if ( raster && pool_base && pool_size >= 4096 )
+ {
+ /* save the pool */
+ raster->buff = (PLong)pool_base;
+ raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
+ }
+ }
+
+
+ static
+ void ft_black_set_mode( TRaster_Instance* raster,
+ unsigned long mode,
+ const char* palette )
+ {
+ if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+ {
+ /* set 5-levels gray palette */
+ raster->grays[0] = palette[0];
+ raster->grays[1] = palette[1];
+ raster->grays[2] = palette[2];
+ raster->grays[3] = palette[3];
+ raster->grays[4] = palette[4];
+ }
+ }
+
+
+ static
+ int ft_black_render( TRaster_Instance* raster,
+ FT_Raster_Params* params )
+ {
+ FT_Outline* outline = (FT_Outline*)params->source;
+ FT_Bitmap* target_map = params->target;
+
+
+ if ( !raster || !raster->buff || !raster->sizeBuff )
+ return Raster_Err_Not_Ini;
+
+ if ( !outline || !outline->contours || !outline->points )
+ return Raster_Err_Invalid;
+
+ /* return immediately if the outline is empty */
+ if ( outline->n_points == 0 || outline->n_contours <= 0 )
+ return Raster_Err_None;
+
+ if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+ return Raster_Err_Invalid;
+
+ if ( !target_map || !target_map->buffer )
+ return Raster_Err_Invalid;
+
+ /* this version of the raster does not support direct rendering, sorry */
+ if ( params->flags & ft_raster_flag_direct )
+ return Raster_Err_Unsupported;
+
+ ras.outline = *outline;
+ ras.target = *target_map;
+
+ return ( params->flags & ft_raster_flag_aa
+ ? Render_Gray_Glyph( raster )
+ : Render_Glyph( raster ) );
+ }
+
+
+ FT_Raster_Funcs ft_standard_raster =
+ {
+ ft_glyph_format_outline,
+ (FT_Raster_New_Func) ft_black_new,
+ (FT_Raster_Reset_Func) ft_black_reset,
+ (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+ (FT_Raster_Render_Func) ft_black_render,
+ (FT_Raster_Done_Func) ft_black_done
+ };
+
+
+/* END */
--- /dev/null
+++ b/src/renderer/ftraster.h
@@ -1,0 +1,48 @@
+/***************************************************************************/
+/* */
+/* ftraster.h */
+/* */
+/* The FreeType glyph rasterizer (specification). */
+/* */
+/* Copyright 1996-2000 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* This file is part of the FreeType project, and may only be used */
+/* modified and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+
+#ifndef FTRASTER_H
+#define FTRASTER_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include <freetype/ftimage.h>
+
+ /*************************************************************************/
+ /* */
+ /* Uncomment the following line if you are using ftraster.c as a */
+ /* standalone module, fully independent of FreeType. */
+ /* */
+/* #define _STANDALONE_ */
+
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR(x) extern x
+#endif
+
+ FT_EXPORT_VAR(FT_Raster_Funcs) ft_standard_raster;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* FTRASTER_H */
+
+
+/* END */
--- /dev/null
+++ b/src/renderer/ftrender.c
@@ -1,0 +1,161 @@
+#include <freetype/internal/ftobjs.h>
+
+ /* sets render-specific mode */
+ static FT_Error ft_renderer_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode(
+ render->raster, mode_tag, data );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static FT_Error ft_renderer_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_UInt mode )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_BBox cbox;
+ FT_UInt width, height, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+
+ FT_Raster_Params params;
+
+ /* first of all, transform the outline */
+ if (slot->format != ft_glyph_format_outline)
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ outline = &slot->outline;
+
+ FT_Outline_Transform( outline, &slot->transform_matrix );
+ FT_Outline_Translate( outline, slot->transform_delta.x,
+ slot->transform_delta.y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = (cbox.xMax+63) & -64;
+ cbox.yMax = (cbox.yMax+63) & -64;
+
+ width = (cbox.xMax - cbox.xMin) >> 6;
+ height = (cbox.yMax - cbox.yMin) >> 6;
+ bitmap = &slot->bitmap;
+ memory = slot->face->memory;
+
+ /* release old bitmap buffer */
+ if ((slot->flags & ft_glyph_own_bitmap))
+ FREE(bitmap->buffer);
+
+ /* allocate new one, depends on pixel format */
+ if ( mode & ft_render_mode_antialias )
+ {
+ pitch = width;
+ bitmap->pixel_mode = ft_pixel_mode_grays;
+ bitmap->num_grays = 256;
+ }
+ else
+ {
+ pitch = (width+7) >> 3;
+ bitmap->pixel_mode = ft_pixel_mode_mono;
+ }
+
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ if (ALLOC( bitmap->buffer, (FT_ULong)pitch * height ))
+ goto Exit;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = 0;
+
+ if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+ params.flags |= ft_raster_flag_aa;
+
+ /* render outline into the bitmap */
+ error = render->render( render->raster, ¶ms );
+ if (error) goto Exit;
+
+ slot->format = ft_glyph_format_bitmap;
+ slot->bitmap_left = cbox.xMin >> 6;
+ slot->bitmap_top = cbox.yMax >> 6;
+
+ Exit:
+ return error;
+ }
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+
+#include <freetype/ftraster.h>
+
+ const FT_Renderer_Class ft_standard_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "standard renderer",
+ 0x10000,
+ 0x20000,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor) 0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_renderer_render,
+ (FTRenderer_setMode) ft_renderer_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+#endif /* !FT_CONFIG_OPTION_NO_STD_RASTER */
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+
+#include <freetype/ftgrays.h>
+
+ const FT_Renderer_Class ft_smooth_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "smooth renderer",
+ 0x10000,
+ 0x20000,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor) 0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_renderer_render,
+ (FTRenderer_setMode) ft_renderer_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+#endif /* !FT_CONFIG_OPTION_NO_SMOOTH_RASTER */
--- /dev/null
+++ b/src/renderer/module.mk
@@ -1,0 +1,11 @@
+make_module_list: add_renderer_module
+
+# XXX: important, the standard renderer *MUST* be first on this list..
+#
+add_renderer_module:
+ $(OPEN_DRIVER)ft_standard_renderer_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)standard $(ECHO_DRIVER_DESC)standard outline renderer module$(ECHO_DRIVER_DONE)
+ $(OPEN_DRIVER)ft_smooth_renderer_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)smooth $(ECHO_DRIVER_DESC)smooth outline renderer module$(ECHO_DRIVER_DONE)
+
+# EOF
--- /dev/null
+++ b/src/renderer/renderer.c
@@ -1,0 +1,219 @@
+#include <freetype/internal/ftobjs.h>
+
+ /* initialise renderer - init its raster */
+ static FT_Error ft_renderer_init( FT_Renderer render )
+ {
+ FT_Library library = FT_MODULE_LIBRARY(render);
+
+ render->clazz->raster_class->raster_reset( render->raster,
+ library->raster_pool, library->raster_pool_size );
+
+ return 0;
+ }
+
+
+
+ /* sets render-specific mode */
+ static FT_Error ft_renderer_set_mode( FT_Renderer render,
+ FT_ULong mode_tag,
+ FT_Pointer data )
+ {
+ /* we simply pass it to the raster */
+ return render->clazz->raster_class->raster_set_mode(
+ render->raster, mode_tag, data );
+ }
+
+ /* transform a given glyph image */
+ static FT_Error ft_renderer_transform( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_Matrix* matrix,
+ FT_Vector* delta )
+ {
+ FT_Error error = FT_Err_Ok;
+
+ if (slot->format != render->glyph_format)
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ if (matrix)
+ FT_Outline_Transform( &slot->outline, matrix );
+
+ if (delta)
+ FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+ Exit:
+ return error;
+ }
+
+ /* return the glyph's control box */
+ static void ft_renderer_get_cbox( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_BBox *cbox )
+ {
+ MEM_Set( cbox, 0, sizeof(*cbox) );
+
+ if (slot->format == render->glyph_format)
+ FT_Outline_Get_CBox( &slot->outline, cbox );
+ }
+
+
+ /* convert a slot's glyph image into a bitmap */
+ static FT_Error ft_renderer_render( FT_Renderer render,
+ FT_GlyphSlot slot,
+ FT_UInt mode,
+ FT_Vector* origin )
+ {
+ FT_Error error;
+ FT_Outline* outline;
+ FT_BBox cbox;
+ FT_UInt width, height, pitch;
+ FT_Bitmap* bitmap;
+ FT_Memory memory;
+
+ FT_Raster_Params params;
+
+ /* check glyph image format */
+ if (slot->format != render->glyph_format)
+ {
+ error = FT_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ outline = &slot->outline;
+
+ /* translate the outline to the new origin if needed */
+ if (origin)
+ FT_Outline_Translate( outline, origin->x, origin->y );
+
+ /* compute the control box, and grid fit it */
+ FT_Outline_Get_CBox( outline, &cbox );
+
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = (cbox.xMax+63) & -64;
+ cbox.yMax = (cbox.yMax+63) & -64;
+
+ width = (cbox.xMax - cbox.xMin) >> 6;
+ height = (cbox.yMax - cbox.yMin) >> 6;
+ bitmap = &slot->bitmap;
+ memory = slot->face->memory;
+
+ /* release old bitmap buffer */
+ if ((slot->flags & ft_glyph_own_bitmap))
+ {
+ FREE(bitmap->buffer);
+ slot->flags &= ~ft_glyph_own_bitmap;
+ }
+
+ /* allocate new one, depends on pixel format */
+ if ( mode & ft_render_mode_antialias )
+ {
+ pitch = width;
+ bitmap->pixel_mode = ft_pixel_mode_grays;
+ bitmap->num_grays = 256;
+ }
+ else
+ {
+ pitch = (width+7) >> 3;
+ bitmap->pixel_mode = ft_pixel_mode_mono;
+ }
+
+ bitmap->width = width;
+ bitmap->rows = height;
+ bitmap->pitch = pitch;
+
+ if (ALLOC( bitmap->buffer, (FT_ULong)pitch * height ))
+ goto Exit;
+
+ slot->flags |= ft_glyph_own_bitmap;
+
+ /* translate outline to render it into the bitmap */
+ FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+
+ /* set up parameters */
+ params.target = bitmap;
+ params.source = outline;
+ params.flags = 0;
+
+ if ( bitmap->pixel_mode == ft_pixel_mode_grays )
+ params.flags |= ft_raster_flag_aa;
+
+ /* render outline into the bitmap */
+ error = render->raster_render( render->raster, ¶ms );
+ if (error) goto Exit;
+
+ slot->format = ft_glyph_format_bitmap;
+ slot->bitmap_left = cbox.xMin >> 6;
+ slot->bitmap_top = cbox.yMax >> 6;
+
+ Exit:
+ return error;
+ }
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+
+#include <freetype/ftraster.h>
+
+ const FT_Renderer_Class ft_standard_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "standard renderer",
+ 0x10000,
+ 0x20000,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor) ft_renderer_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_renderer_render,
+ (FTRenderer_transform) ft_renderer_transform,
+ (FTRenderer_getCBox) ft_renderer_get_cbox,
+ (FTRenderer_setMode) ft_renderer_set_mode,
+
+ (FT_Raster_Funcs*) &ft_standard_raster
+ };
+
+#endif /* !FT_CONFIG_OPTION_NO_STD_RASTER */
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+
+#include <freetype/ftgrays.h>
+
+ const FT_Renderer_Class ft_smooth_renderer_class =
+ {
+ {
+ ft_module_renderer,
+ sizeof( FT_RendererRec ),
+
+ "smooth renderer",
+ 0x10000,
+ 0x20000,
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor) ft_renderer_init,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+ },
+
+ ft_glyph_format_outline,
+
+ (FTRenderer_render) ft_renderer_render,
+ (FTRenderer_transform) ft_renderer_transform,
+ (FTRenderer_getCBox) ft_renderer_get_cbox,
+ (FTRenderer_setMode) ft_renderer_set_mode,
+
+ (FT_Raster_Funcs*) &ft_grays_raster
+ };
+
+#endif /* !FT_CONFIG_OPTION_NO_SMOOTH_RASTER */
--- /dev/null
+++ b/src/renderer/renderer.h
@@ -1,0 +1,14 @@
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include <freetype/ftrender.h>
+
+#ifndef FT_CONFIG_OPTION_NO_STD_RASTER
+ FT_EXPORT_VAR(const FT_Renderer_Class) ft_std_renderer_class;
+#endif
+
+#ifndef FT_CONFIG_OPTION_NO_SMOOTH_RASTER
+ FT_EXPORT_VAR(const FT_Renderer_Class) ft_smooth_renderer_class;
+#endif
+
+#endif /* RENDERER_H */
--- /dev/null
+++ b/src/renderer/rules.mk
@@ -1,0 +1,75 @@
+#
+# FreeType 2 renderer module build 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.
+
+
+# renderer driver directory
+#
+REND_DIR := $(SRC_)renderer
+REND_DIR_ := $(REND_DIR)$(SEP)
+
+
+# additional include flags used when compiling the driver
+#
+REND_INCLUDE := $(REND_DIR)
+
+# compilation flags for the driver
+#
+REND_CFLAGS := $(REND_INCLUDE:%=$I%)
+REND_COMPILE := $(FT_COMPILE) $(REND_CFLAGS)
+
+
+# REND driver sources (i.e., C files)
+#
+REND_DRV_SRC := $(REND_DIR_)ftraster.c \
+ $(REND_DIR_)ftgrays.c \
+ $(REND_DIR_)renderer.c
+
+# REND driver headers
+#
+REND_DRV_H := $(REND_DRV_SRC:%c=%h)
+
+
+# REND driver object(s)
+#
+# REND_DRV_OBJ_M is used during `multi' builds.
+# REND_DRV_OBJ_S is used during `single' builds.
+#
+REND_DRV_OBJ_M := $(REND_DRV_SRC:$(REND_DIR_)%.c=$(OBJ_)%.$O)
+REND_DRV_OBJ_S := $(REND_DRV_OBJ_M)
+
+# REND driver source file for single build
+#
+#REND_DRV_SRC_S := $(REND_DIR_)renderer.c
+
+
+# REND driver - single object
+#
+#$(REND_DRV_OBJ_S): $(REND_DRV_SRC_S) $(REND_DRV_SRC) \
+# $(FREETYPE_H) $(REND_DRV_H)
+# $(REND_COMPILE) $T$@ $(REND_DRV_SRC_S)
+
+
+# REND driver - multiple objects
+#
+$(OBJ_)%.$O: $(REND_DIR_)%.c $(FREETYPE_H) $(REND_DRV_H)
+ $(REND_COMPILE) $T$@ $<
+
+
+# update main driver object lists
+#
+DRV_OBJS_S += $(REND_DRV_OBJ_M)
+DRV_OBJS_M += $(REND_DRV_OBJ_M)
+
+
+# EOF
--- a/src/sfnt/module.mk
+++ b/src/sfnt/module.mk
@@ -1,7 +1,7 @@
-make_module_list: add_sfnt_driver
+make_module_list: add_sfnt_module
-add_sfnt_driver:
- $(OPEN_DRIVER)sfnt_driver_interface$(CLOSE_DRIVER)
- $(ECHO_DRIVER)sfnt $(ECHO_DRIVER_DESC)pseudo-driver for TrueType & OpenType formats$(ECHO_DRIVER_DONE)
+add_sfnt_module:
+ $(OPEN_DRIVER)sfnt_module_class$(CLOSE_DRIVER)
+ $(ECHO_DRIVER)sfnt $(ECHO_DRIVER_DESC)helper module for TrueType & OpenType formats$(ECHO_DRIVER_DONE)
# EOF
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -25,7 +25,6 @@
#include <ttcmap.h>
#include <sfobjs.h>
-
static
void* get_sfnt_table( TT_Face face,
FT_Sfnt_Tag tag )
@@ -72,13 +71,13 @@
static
- FTDriver_Interface SFNT_Get_Interface( FT_Driver driver,
- const char* interface )
+ FT_Module_Interface SFNT_Get_Interface( FT_Module module,
+ const char* interface )
{
- UNUSED( driver );
+ UNUSED( module );
if ( strcmp( interface, "get_sfnt" ) == 0 )
- return (FTDriver_Interface)get_sfnt_table;
+ return (FT_Module_Interface)get_sfnt_table;
return 0;
}
@@ -140,22 +139,22 @@
};
- const FT_DriverInterface sfnt_driver_interface =
+ const FT_Module_Class sfnt_module_class =
{
- sizeof ( FT_DriverRec ), 0, 0, 0,
-
- "sfnt", /* driver name */
- 1, /* driver version */
- 2, /* driver requires FreeType 2 or higher */
-
- (void*)&sfnt_interface,
-
- 0, 0, 0,
- 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0,
- 0,
+ 0, /* not a font driver or renderer */
+ sizeof( FT_ModuleRec ),
+
+ "sfnt", /* driver name */
+ 0x10000, /* driver version 1.0 */
+ 0x20000, /* driver requires FreeType 2.0 or higher */
+
+ (const void*)&sfnt_interface, /* module specific interface */
+
+ (FT_Module_Constructor) 0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) SFNT_Get_Interface
};
+
/* END */
--- a/src/sfnt/sfdriver.h
+++ b/src/sfnt/sfdriver.h
@@ -19,10 +19,9 @@
#ifndef SFDRIVER_H
#define SFDRIVER_H
-#include <freetype/internal/ftdriver.h>
-#include <freetype/internal/ftobjs.h>
+#include <freetype/ftmodule.h>
- FT_EXPORT_VAR(const FT_DriverInterface) sfnt_driver_interface;
+ FT_EXPORT_VAR(const FT_Module_Class) sfnt_module_class;
#endif /* SFDRIVER_H */
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -180,8 +180,8 @@
FT_Parameter* params )
{
FT_Error error;
+ FT_Library library = face->root.driver->root.library;
SFNT_Interface* sfnt;
- PSNames_Interface* psnames;
SFNT_Header sfnt_header;
/* for now, parameters are unused */
@@ -188,22 +188,10 @@
UNUSED( num_params );
UNUSED( params );
-
sfnt = (SFNT_Interface*)face->sfnt;
if ( !sfnt )
{
- /* look-up the SFNT driver */
- FT_Driver sfnt_driver;
-
-
- sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" );
- if ( !sfnt_driver )
- {
- error = FT_Err_Invalid_File_Format;
- goto Exit;
- }
-
- sfnt = (SFNT_Interface*)( sfnt_driver->interface.format_interface );
+ sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
if ( !sfnt )
{
error = FT_Err_Invalid_File_Format;
@@ -214,17 +202,10 @@
face->goto_table = sfnt->goto_table;
}
- psnames = (PSNames_Interface*)face->psnames;
- if ( !psnames )
+ if ( !face->psnames )
{
- /* look-up the PSNames driver */
- FT_Driver psnames_driver;
-
-
- psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
- if ( psnames_driver )
- face->psnames = (PSNames_Interface*)
- ( psnames_driver->interface.format_interface );
+ face->psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( library, "psnames" );
}
/* check that we have a valid TrueType file */
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -59,7 +59,7 @@
/* table :: A pointer to a cmap object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* The function assumes that the stream is already in use (i.e., */
@@ -281,7 +281,7 @@
/* cmap :: A handle to a cmap object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_CharMap_Free( TT_Face face,
@@ -293,7 +293,7 @@
if ( !cmap )
return TT_Err_Ok;
- memory = face->root.driver->memory;
+ memory = face->root.driver->root.memory;
switch ( cmap->format )
{
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -96,7 +96,7 @@
/* length :: The length of the table if found, undefined otherwise. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Goto_Table( TT_Face face,
@@ -141,7 +141,7 @@
/* sfnt :: The SFNT header. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* The stream cursor must be at the font file's origin. */
@@ -275,7 +275,7 @@
/* sfnt :: The SFNT directory header. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* The stream cursor must be at the font file's origin. */
@@ -373,7 +373,7 @@
/* buffer :: The address of target buffer. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Any( TT_Face face,
@@ -436,7 +436,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Header( TT_Face face,
@@ -507,7 +507,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_MaxProfile( TT_Face face,
@@ -597,7 +597,7 @@
/* vertical :: A boolean flag. If set, load vertical metrics. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error TT_Load_Metrics( TT_Face face,
@@ -733,7 +733,7 @@
/* vertical :: A boolean flag. If set, load vertical metrics. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Metrics_Header( TT_Face face,
@@ -829,7 +829,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Names( TT_Face face,
@@ -990,7 +990,7 @@
LOCAL_FUNC
void TT_Free_Names( TT_Face face )
{
- FT_Memory memory = face->root.driver->memory;
+ FT_Memory memory = face->root.driver->root.memory;
TT_NameTable* names = &face->name_table;
@@ -1020,7 +1020,7 @@
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_CMap( TT_Face face,
@@ -1129,7 +1129,7 @@
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_OS2( TT_Face face,
@@ -1263,7 +1263,7 @@
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_PostScript( TT_Face face,
@@ -1318,7 +1318,7 @@
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_PCLT( TT_Face face,
@@ -1389,7 +1389,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Gasp( TT_Face face,
@@ -1461,7 +1461,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Kern( TT_Face face,
@@ -1566,7 +1566,7 @@
/* stream :: A handle to the input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Hdmx( TT_Face face,
@@ -1652,7 +1652,7 @@
if ( face )
{
FT_Int n;
- FT_Memory memory = face->root.driver->memory;
+ FT_Memory memory = face->root.driver->root.memory;
for ( n = 0; n < face->hdmx.num_records; n++ )
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -427,7 +427,7 @@
/* You must not modify the returned string! */
/* */
/* <Output> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Get_PS_Name( TT_Face face,
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -211,7 +211,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Load_SBit_Const_Metrics( TT_SBit_Range* range,
@@ -243,7 +243,7 @@
/* load_offsets :: A flag whether to load the glyph offset table. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Load_SBit_Range_Codes( TT_SBit_Range* range,
@@ -306,7 +306,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Load_SBit_Range( TT_SBit_Range* range,
@@ -381,7 +381,7 @@
/* stream :: The input stream. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_SBit_Strikes( TT_Face face,
@@ -631,7 +631,7 @@
/* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
/* */
/* <Return> */
- /* FreeType error code. 0 means the glyph index was found. */
+ /* TrueType error code. 0 means the glyph index was found. */
/* */
static
FT_Error Find_SBit_Range( FT_UInt glyph_index,
@@ -735,7 +735,7 @@
/* aglyph_offset :: The offset of the glyph data in `EBDT' table. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. Returns */
+ /* TrueType error code. 0 means success. Returns */
/* TT_Err_Invalid_Argument if no sbit exists for the requested glyph. */
/* */
static
@@ -800,7 +800,7 @@
/* big_metrics :: A big SBit metrics structure for the glyph. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* The stream cursor must be positioned at the glyph's offset within */
@@ -1349,7 +1349,7 @@
/* metrics :: A big sbit metrics structure for the glyph image. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. Returns an error if no */
+ /* TrueType error code. 0 means success. Returns an error if no */
/* glyph sbit exists for the index. */
/* */
/* <Note> */
--- a/src/truetype/module.mk
+++ b/src/truetype/module.mk
@@ -1,7 +1,7 @@
make_module_list: add_truetype_driver
add_truetype_driver:
- $(OPEN_DRIVER)tt_driver_interface$(CLOSE_DRIVER)
+ $(OPEN_DRIVER)tt_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)truetype $(ECHO_DRIVER_DESC)Windows/Mac font files with extension *.ttf or *.ttc$(ECHO_DRIVER_DONE)
# EOF
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -75,7 +75,7 @@
/* formats. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only horizontal layouts (left-to-right & right-to-left) are */
@@ -178,7 +178,7 @@
/* size :: A handle to the target size object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Set_Char_Sizes( TT_Size size,
@@ -238,7 +238,7 @@
/* size :: A handle to the target size object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Set_Pixel_Sizes( TT_Size size,
@@ -280,7 +280,7 @@
/* whether to hint the outline, etc). */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Load_Glyph( TT_GlyphSlot slot,
@@ -398,19 +398,18 @@
static
- FTDriver_Interface tt_get_interface( TT_Driver driver,
- const char* interface )
+ FT_Module_Interface tt_get_interface( TT_Driver driver,
+ const char* interface )
{
- FT_Driver sfntd = FT_Get_Driver( driver->root.library, "sfnt" );
+ FT_Module sfntd = FT_Get_Module( driver->root.root.library, "sfnt" );
SFNT_Interface* sfnt;
-
/* only return the default interface from the SFNT module */
if ( sfntd )
{
- sfnt = (SFNT_Interface*)(sfntd->interface.format_interface);
+ sfnt = (SFNT_Interface*)(sfntd->clazz->module_interface);
if ( sfnt )
- return sfnt->get_interface( (FT_Driver)driver, interface );
+ return sfnt->get_interface( FT_MODULE(driver), interface );
}
return 0;
@@ -419,37 +418,45 @@
/* The FT_DriverInterface structure is defined in ftdriver.h. */
- const FT_DriverInterface tt_driver_interface =
+ const FT_Driver_Class tt_driver_class =
{
- sizeof ( TT_DriverRec ),
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof ( TT_DriverRec ),
+
+ "truetype", /* driver name */
+ 0x10000, /* driver version == 1.0 */
+ 0x20000, /* driver requires FreeType 2.0 or above */
+
+ (void*)0, /* driver specific interface */
+
+ (FT_Module_Constructor) TT_Init_Driver,
+ (FT_Module_Destructor) TT_Done_Driver,
+ (FT_Module_Requester) tt_get_interface,
+ },
+
sizeof ( TT_FaceRec ),
sizeof ( TT_SizeRec ),
sizeof ( FT_GlyphSlotRec ),
- "truetype", /* driver name */
- 100, /* driver version == 1.0 */
- 200, /* driver requires FreeType 2.0 or above */
- (void*)0,
-
- (FTDriver_initDriver) TT_Init_Driver,
- (FTDriver_doneDriver) TT_Done_Driver,
- (FTDriver_getInterface) tt_get_interface,
-
(FTDriver_initFace) TT_Init_Face,
(FTDriver_doneFace) TT_Done_Face,
- (FTDriver_getKerning) Get_Kerning,
-
(FTDriver_initSize) TT_Init_Size,
(FTDriver_doneSize) TT_Done_Size,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
+
(FTDriver_setCharSizes) Set_Char_Sizes,
(FTDriver_setPixelSizes) Set_Pixel_Sizes,
-
- (FTDriver_initGlyphSlot) TT_Init_GlyphSlot,
- (FTDriver_doneGlyphSlot) TT_Done_GlyphSlot,
(FTDriver_loadGlyph) Load_Glyph,
-
(FTDriver_getCharIndex) Get_Char_Index,
+
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) 0,
+ (FTDriver_getAdvances) 0
+
+
};
@@ -475,9 +482,9 @@
/* format-specific interface can then be retrieved through the method */
/* interface->get_format_interface. */
/* */
- EXPORT_FUNC( FT_DriverInterface* ) getDriverInterface( void )
+ EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
{
- return &tt_driver_interface;
+ return &tt_driver_class;
}
--- a/src/truetype/ttdriver.h
+++ b/src/truetype/ttdriver.h
@@ -25,7 +25,7 @@
#include <freetype/internal/tterrors.h>
- FT_EXPORT_VAR( const FT_DriverInterface ) tt_driver_interface;
+ FT_EXPORT_VAR( const FT_Driver_Class ) tt_driver_class;
#endif /* TTDRIVER_H */
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -174,32 +174,20 @@
}
- /*************************************************************************/
- /* */
- /* Mounts one glyph zone on top of another. This is needed to */
- /* assemble composite glyphs. */
- /* */
- static
- void mount_zone( TT_GlyphZone* source,
- TT_GlyphZone* target )
+ static void tt_prepare_zone( TT_GlyphZone* zone,
+ FT_GlyphLoad* load,
+ FT_UInt start_point,
+ FT_UInt start_contour )
{
- FT_UInt np;
- FT_Int nc;
+ zone->n_points = load->outline.n_points - start_point;
+ zone->n_contours = load->outline.n_contours - start_contour;
+ zone->org = load->extra_points + start_point;
+ zone->cur = load->outline.points + start_point;
+ zone->tags = (FT_Byte*)load->outline.tags + start_point;
+ zone->contours = (FT_UShort*)load->outline.contours + start_contour;
+ }
- 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 )
@@ -220,54 +208,43 @@
FT_Int n_contours,
FT_Bool debug )
{
- FT_Error error;
- FT_Stream stream = load->stream;
- TT_GlyphZone* zone = &load->zone;
- TT_Face face = load->face;
+ FT_Error error;
+ FT_Stream stream = load->stream;
+ FT_GlyphLoader* gloader = load->gloader;
+ FT_Outline* outline;
+ TT_GlyphZone* zone = &load->zone;
+ TT_Face face = load->face;
- FT_UShort n_ins;
- FT_Int n, n_points;
+ 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();
+ /* reading the contours endpoints & number of points */
+ {
+ short* cur = gloader->current.outline.contours;
+ short* limit = cur + n_contours;
+
+ for ( ; cur < limit; cur++ )
+ cur[0] = GET_UShort();
+
+ n_points = 0;
+ if (n_contours > 0)
+ n_points = cur[-1]+1;
- n_points = 0;
- if ( n_contours > 0 )
- n_points = zone->contours[n_contours - 1] + 1;
+ error = FT_GlyphLoader_Check_Points( gloader, n_points+2, 0 );
+ if (error) goto Fail;
+
+ outline = &gloader->current.outline;
+ }
- /* reading the bytecode instructions */
+ /* 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_TRACE5(( " Instructions size: %d\n", n_ins ));
if ( n_ins > face->max_profile.maxSizeOfInstructions )
@@ -302,11 +279,10 @@
/* reading the point tags */
{
- FT_Byte* flag = load->zone.tags;
+ FT_Byte* flag = (FT_Byte*)outline->tags;
FT_Byte* limit = flag + n_points;
FT_Byte c, count;
-
for ( ; flag < limit; flag++ )
{
*flag = c = GET_Byte();
@@ -321,9 +297,9 @@
/* reading the X coordinates */
{
- FT_Vector* vec = zone->org;
+ FT_Vector* vec = outline->points;
FT_Vector* limit = vec + n_points;
- FT_Byte* flag = zone->tags;
+ FT_Byte* flag = (FT_Byte*)outline->tags;
FT_Pos x = 0;
@@ -349,9 +325,9 @@
/* reading the Y coordinates */
{
- FT_Vector* vec = zone->org;
+ FT_Vector* vec = gloader->current.outline.points;
FT_Vector* limit = vec + n_points;
- FT_Byte* flag = zone->tags;
+ FT_Byte* flag = (FT_Byte*)outline->tags;
FT_Pos x = 0;
@@ -387,7 +363,7 @@
/* pp1 = xMin - lsb */
- pp1 = zone->org + n_points;
+ pp1 = outline->points + n_points;
pp1->x = load->bbox.xMin - load->left_bearing;
pp1->y = 0;
@@ -398,34 +374,30 @@
/* clear the touch tags */
for ( n = 0; n < n_points; n++ )
- zone->tags[n] &= FT_Curve_Tag_On;
+ outline->tags[n] &= FT_Curve_Tag_On;
- zone->tags[n_points ] = 0;
- zone->tags[n_points + 1] = 0;
+ outline->tags[n_points ] = 0;
+ outline->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;
+ outline->n_points = n_points;
+ outline->n_contours = n_contours;
+ n_points += 2;
- /* now eventually scale and hint the glyph */
+ /* set up zone for hinting */
+ tt_prepare_zone( zone, &gloader->current, 0, 0 );
- if ( load->load_flags & FT_LOAD_NO_SCALE )
+ /* eventually scale 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_Vector* vec = zone->cur;
+ 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++ )
{
@@ -432,40 +404,37 @@
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;
+ cur_to_org( n_points, zone );
+ /* eventually hint the glyph */
+ if ( IS_HINTED(load->load_flags) )
+ {
+ FT_Pos x = zone->org[n_points-2].x;
- x = ( ( x + 32 ) & -64 ) - x;
- translate_array( n_points, zone->org, x, 0 );
+ x = ( ( x + 32 ) & -64 ) - x;
+ translate_array( n_points, zone->org, x, 0 );
- org_to_cur( n_points, zone );
+ org_to_cur( n_points, zone );
- zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
+ zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- /* now consider hinting */
- if ( n_ins > 0 )
- {
- load->exec->is_composite = FALSE;
- load->exec->pedantic_hinting = (FT_Bool)(load->load_flags &
- FT_LOAD_PEDANTIC);
- load->exec->pts = *zone;
- load->exec->pts.n_points += 2;
+ /* now consider hinting */
+ if ( n_ins > 0 )
+ {
+ load->exec->is_composite = FALSE;
+ load->exec->pedantic_hinting = (FT_Bool)(load->load_flags &
+ FT_LOAD_PEDANTIC);
+ load->exec->pts = *zone;
+ load->exec->pts.n_points += 2;
- error = TT_Run_Context( load->exec, debug );
- if ( error && load->exec->pedantic_hinting )
- return error;
- }
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+ error = TT_Run_Context( load->exec, debug );
+ if ( error && load->exec->pedantic_hinting )
+ return error;
}
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
}
/* save glyph phantom points */
@@ -475,7 +444,7 @@
load->pp2 = zone->cur[n_points - 1];
}
- return TT_Err_Ok;
+ return FT_Err_Ok;
Fail:
FORGET_Frame();
@@ -496,14 +465,15 @@
FT_Error load_truetype_glyph( TT_Loader* loader,
FT_UInt glyph_index )
{
- FT_Stream stream = loader->stream;
- FT_Error error;
- TT_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;
+ FT_Stream stream = loader->stream;
+ FT_Error error;
+ TT_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;
+ FT_GlyphLoader* gloader = loader->gloader;
/* check glyph index */
@@ -596,13 +566,6 @@
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;
@@ -622,9 +585,10 @@
if ( contours_count >= 0 )
{
- FT_UInt num_base_points;
+ /* check that we can add the contours to the glyph */
+ error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
+ if (error) goto Fail;
-
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
error = Load_Simple( loader,
count,
@@ -634,31 +598,12 @@
#else
error = Load_Simple( loader, count, contours_count, 0 );
#endif
- if ( error )
- goto Fail;
+ if ( error ) goto Fail;
+ FT_GlyphLoader_Add( gloader );
+
/* 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;
}
/***********************************************************************/
@@ -669,9 +614,14 @@
else
{
/* for each subglyph, read composite header */
- TT_GlyphSlot glyph = loader->glyph;
- FT_SubGlyph* subglyph = glyph->subglyphs + glyph->num_subglyphs;
+ TT_GlyphSlot glyph = loader->glyph;
+ FT_SubGlyph* subglyph;
+ FT_UInt num_base_subgs;
+ FT_UInt start_point, start_contour;
+ start_point = gloader->base.outline.n_points;
+ start_contour = gloader->base.outline.n_contours;
+
if ( ACCESS_Frame( count ) )
goto Fail;
@@ -679,29 +629,13 @@
do
{
FT_Fixed xx, xy, yy, yx;
- FT_UInt total_subglyphs;
+ /* check that we can load a new subglyph */
+ error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs+1 );
+ if (error) goto Fail;
+
+ subglyph = gloader->current.subglyphs + num_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();
@@ -746,11 +680,12 @@
subglyph->transform.yx = yx;
subglyph->transform.yy = yy;
- subglyph++;
num_subglyphs++;
}
- while (subglyph[-1].flags & MORE_COMPONENTS);
+ while (subglyph->flags & MORE_COMPONENTS);
+ gloader->current.num_subglyphs = num_subglyphs;
+
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
{
/* we must undo the ACCESS_Frame in order to point to the */
@@ -769,8 +704,12 @@
if ( loader->load_flags & FT_LOAD_NO_RECURSE )
{
/* set up remaining glyph fields */
- glyph->num_subglyphs += num_subglyphs;
+ FT_GlyphLoader_Add( gloader );
+
+ glyph->num_subglyphs = gloader->base.num_subglyphs;
glyph->format = ft_glyph_format_composite;
+ glyph->subglyphs = gloader->base.subglyphs;
+
goto Load_End;
}
@@ -784,25 +723,32 @@
{
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++ )
+ num_base_subgs = gloader->base.num_subglyphs;
+
+ FT_GlyphLoader_Add( gloader );
+
+ for ( n = 0; n < num_subglyphs; n++ )
{
FT_Vector pp1, pp2;
FT_Pos x, y;
+ /* each time we call load_truetype_glyph in this loop, the */
+ /* value of 'gloader.base.subglyphs' can change due to table */
+ /* reallocations. We thus need to recompute the subglyph */
+ /* pointer on each iteration.. */
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
pp1 = loader->pp1;
pp2 = loader->pp2;
- num_base_points = loader->base.n_points;
+ num_base_points = gloader->base.outline.n_points;
error = load_truetype_glyph( loader, subglyph->index );
if ( error )
goto Fail;
+ subglyph = gloader->base.subglyphs + num_base_subgs + n;
+
if ( subglyph->flags & USE_MY_METRICS )
{
pp1 = loader->pp1;
@@ -814,8 +760,7 @@
loader->pp2 = pp2;
}
- num_points = loader->base.n_points;
- num_contours = loader->base.n_contours;
+ num_points = gloader->base.outline.n_points;
num_new_points = num_points - num_base_points;
@@ -825,33 +770,14 @@
WE_HAVE_AN_XY_SCALE |
WE_HAVE_A_2X2 ) )
{
- FT_Vector* cur = loader->zone.cur;
- FT_Vector* org = loader->zone.org;
+ FT_Vector* cur = gloader->base.outline.points + num_base_points;
+ FT_Vector* org = gloader->base.extra_points + num_base_points;
FT_Vector* limit = cur + num_new_points;
-
for ( ; cur < limit; cur++, org++ )
{
- FT_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;
+ FT_Vector_Transform( cur, &subglyph->transform );
+ FT_Vector_Transform( org, &subglyph->transform );
}
}
@@ -859,12 +785,13 @@
if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
{
- FT_Int k = subglyph->arg1;
- FT_UInt l = subglyph->arg2;
+ FT_Int k = subglyph->arg1;
+ FT_UInt l = subglyph->arg2;
+ FT_Vector* p1;
+ FT_Vector* p2;
-
- if ( k >= num_base_points ||
- l >= (FT_UInt)num_new_points )
+ if ( start_point + k >= num_base_points ||
+ l >= (FT_UInt)num_new_points )
{
error = TT_Err_Invalid_Composite;
goto Fail;
@@ -872,8 +799,11 @@
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;
+ p1 = gloader->base.outline.points + start_point + k;
+ p2 = gloader->base.outline.points + start_point + l;
+
+ x = p1->x - p2->x;
+ y = p1->y - p2->y;
}
else
{
@@ -906,7 +836,6 @@
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- subglyph--;
if ( num_subglyphs > 0 &&
loader->exec &&
subglyph->flags & WE_HAVE_INSTR )
@@ -949,8 +878,8 @@
goto Fail;
/* prepare the execution context */
- exec->pts = loader->base;
- pts = &exec->pts;
+ tt_prepare_zone( &exec->pts, &gloader->base, start_point, start_contour );
+ pts = &exec->pts;
pts->n_points = num_points + 2;
pts->n_contours = num_contours;
@@ -1007,7 +936,7 @@
/***********************************************************************/
Load_End:
- error = TT_Err_Ok;
+ error = FT_Err_Ok;
Fail:
return error;
@@ -1018,8 +947,6 @@
void compute_glyph_metrics( TT_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;
TT_Face face = loader->face;
FT_Fixed x_scale, y_scale;
@@ -1026,16 +953,6 @@
TT_GlyphSlot glyph = loader->glyph;
TT_Size size = loader->size;
-
- /* when a simple glyph was loaded, the value of */
- /* `base.n_points' and `base.n_contours' is 0, we will */
- /* 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 = 0x10000L;
y_scale = 0x10000L;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
@@ -1046,27 +963,14 @@
if ( glyph->format != ft_glyph_format_composite )
{
- FT_UInt u;
+ glyph->outline.flags &= ~ft_outline_single_pass;
-
- 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.flags &= ~ft_outline_single_pass;
- glyph->outline.n_points = num_points;
- glyph->outline.n_contours = num_contours;
-
+ /* copy outline to our glyph slot */
+ FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader );
+ glyph->outline = glyph->loader->base.outline;
+
/* translate array so that (0,0) is the glyph's origin */
- translate_array( (FT_UShort)( num_points + 2 ),
- glyph->outline.points,
- -loader->pp1.x,
- 0 );
+ FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
FT_Outline_Get_CBox( &glyph->outline, &bbox );
@@ -1082,18 +986,11 @@
else
bbox = loader->bbox;
- /* get the device-independent scaled horizontal metrics; */
- /* take care of fixed-pitch fonts... */
+ /* get the device-independent horizontal advance. It is scaled later */
+ /* by the base layer.. */
{
- FT_Pos left_bearing;
- FT_Pos advance;
+ FT_Pos advance = loader->advance;
- FT_Pos lsb2, adv2;
-
-
- left_bearing = loader->left_bearing;
- advance = loader->advance;
-
/* the flag FT_LOAD_NO_ADVANCE_CHECK was introduced to */
/* correctly support DynaLab fonts, which have an incorrect */
/* `advance_Width_Max' field! It is used, to my knowledge, */
@@ -1103,23 +1000,9 @@
( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
advance = face->horizontal.advance_Width_Max;
- lsb2 = left_bearing;
- adv2 = advance;
-
- /* if necessary, scale the horizontal left bearing and advance */
- /* to get their values in 16.16 format.. */
- if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
- loader->load_flags & FT_LOAD_LINEAR )
- {
- FT_Pos em_size = face->root.units_per_EM;
- FT_Pos pixel_size = (FT_Pos)face->root.size->metrics.x_ppem << 16;
-
-
- lsb2 = FT_MulDiv( lsb2, pixel_size, em_size );
- adv2 = FT_MulDiv( adv2, pixel_size, em_size );
- }
- glyph->metrics2.horiBearingX = lsb2;
- glyph->metrics2.horiAdvance = adv2;
+ /* we need to return the advance in font units in linearHoriAdvance, */
+ /* it will be scaled later by the base layer.. */
+ glyph->linearHoriAdvance = advance;
}
glyph->metrics.horiBearingX = bbox.xMin;
@@ -1184,7 +1067,7 @@
/* 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(). */
+ /* FT_Get_Outline_CBox(). */
/* scale the metrics */
if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
@@ -1201,28 +1084,10 @@
advance = advance_height;
}
- /* compute metrics2 fields */
- {
- FT_Pos vtb2 = top_bearing;
- FT_Pos adv2 = advance_height;
+ /* set the advance height in design units. It is scaled later by the */
+ /* base layer.. */
+ glyph->linearVertAdvance = advance_height;
-
- /* scale to 16.16 format if required */
- if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
- loader->load_flags & FT_LOAD_LINEAR )
- {
- FT_Pos em_size = face->root.units_per_EM;
- FT_Pos pixel_size = face->root.size->metrics.y_ppem;
-
-
- vtb2 = FT_MulDiv( vtb2, pixel_size, em_size );
- adv2 = FT_MulDiv( adv2, pixel_size, em_size );
- }
-
- glyph->metrics2.vertBearingY = vtb2;
- glyph->metrics2.vertAdvance = adv2;
- }
-
/* XXX: for now, we have no better algorithm for the lsb, but it */
/* should work fine. */
/* */
@@ -1251,16 +1116,6 @@
glyph->metrics.horiAdvance = widths[glyph_index] << 6;
}
-/* drop-out mode is irrelevant, we always use mode 2 */
-#if 0
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
- if ( loader->exec )
- glyph->outline.dropout_mode = (FT_Char)loader->exec->GS.scan_type;
-#else
- glyph->outline.dropout_mode = 2;
-#endif
-#endif
-
/* set glyph dimensions */
glyph->metrics.width = bbox.xMax - bbox.xMin;
glyph->metrics.height = bbox.yMax - bbox.yMin;
@@ -1293,7 +1148,7 @@
/* whether to hint the outline, etc). */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Load_Glyph( TT_Size size,
@@ -1307,7 +1162,6 @@
FT_Memory memory;
FT_Error error;
TT_Loader loader;
- TT_GlyphZone* zone;
face = (TT_Face)glyph->face;
@@ -1362,6 +1216,16 @@
glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
glyph->format = ft_glyph_format_bitmap;
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ glyph->bitmap_left = metrics.horiBearingX;
+ glyph->bitmap_top = metrics.horiBearingY;
+ }
+ else
+ {
+ glyph->bitmap_left = metrics.vertBearingX;
+ glyph->bitmap_top = metrics.vertBearingY;
+ }
return error;
}
}
@@ -1368,9 +1232,6 @@
#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... */
@@ -1385,20 +1246,17 @@
MEM_Set( &loader, 0, sizeof ( loader ) );
/* update the glyph zone bounds */
- zone = &((TT_Driver)face->root.driver)->zone;
- error = TT_Update_GlyphZone( zone,
- face->root.max_points,
- face->root.max_contours );
- if ( error )
{
- FT_ERROR(( "TT_Load_Glyph: Could not update loader glyph zone\n" ));
- goto Exit;
+ FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader;
+
+ loader.gloader = gloader;
+
+ FT_GlyphLoader_Rewind( gloader );
+
+ tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
+ tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
}
- loader.base = *zone;
- loader.zone.n_points = 0;
- loader.zone.n_contours = 0;
-
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
if ( size )
@@ -1425,8 +1283,6 @@
/* let's initialize 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;
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -34,6 +34,7 @@
TT_Face face;
TT_Size size;
TT_GlyphSlot glyph;
+ FT_GlyphLoader* gloader;
FT_ULong load_flags;
FT_UInt glyph_index;
@@ -40,8 +41,6 @@
FT_Stream stream;
FT_Int byte_len;
- FT_Int left_points;
- FT_Int left_contours;
FT_BBox bbox;
FT_Int left_bearing;
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -257,7 +257,7 @@
/* exec :: The target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Goto_CodeRange( TT_ExecContext exec,
@@ -307,7 +307,7 @@
/* exec :: The target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Set_CodeRange( TT_ExecContext exec,
@@ -339,7 +339,7 @@
/* exec :: The target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Does not set the Error variable. */
@@ -378,7 +378,7 @@
/* memory :: A handle to the parent memory object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
@@ -433,7 +433,7 @@
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Init_Context( TT_ExecContext exec,
@@ -504,7 +504,7 @@
/* buff :: The address of the buffer base pointer. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
static
FT_Error Update_Max( FT_Memory memory,
@@ -546,7 +546,7 @@
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
@@ -649,7 +649,7 @@
/* size :: A handle to the target size object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
@@ -696,7 +696,7 @@
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueTyoe error code. 0 means success. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
@@ -791,7 +791,7 @@
driver = (TT_Driver)face->root.driver;
- memory = driver->root.memory;
+ memory = driver->root.root.memory;
exec = driver->context;
if ( !driver->context )
@@ -834,7 +834,7 @@
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only the glyph loader and debugger should call this function. */
@@ -6781,7 +6781,7 @@
/* exec :: A handle to the target execution context. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
/* <Note> */
/* Only the object manager and debugger should call this function. */
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -124,65 +124,6 @@
/*************************************************************************/
/* */
/* <Function> */
- /* TT_Update_GlyphZone */
- /* */
- /* <Description> */
- /* Checks the size of a zone and reallocates it if necessary. */
- /* */
- /* <Input> */
- /* newPoints :: The new capacity for points. We add two slots for */
- /* phantom points. */
- /* */
- /* newContours :: The new capacity for contours. */
- /* */
- /* <InOut> */
- /* zone :: The address of the target zone. */
- /* */
- LOCAL_FUNC FT_Error TT_Update_GlyphZone( TT_GlyphZone* zone,
- FT_UShort newPoints,
- FT_Short newContours )
- {
- FT_Error error = FT_Err_Ok;
- FT_Memory memory = zone->memory;
-
-
- newPoints += 2;
-
- if ( zone->max_points < newPoints )
- {
- /* reallocate the points arrays */
- if ( REALLOC_ARRAY( zone->org, zone->max_points * 2,
- newPoints * 2, FT_F26Dot6 ) ||
- REALLOC_ARRAY( zone->cur, zone->max_points * 2,
- newPoints * 2, FT_F26Dot6 ) ||
- REALLOC_ARRAY( zone->tags, zone->max_points * 2,
- newPoints, FT_Byte ) )
- goto Exit;
-
- zone->max_points = newPoints;
- }
-
- if ( zone->max_contours < newContours )
- {
- /* reallocate the contours array */
- if ( REALLOC_ARRAY( zone->contours, zone->max_contours,
- newContours, FT_UShort ) )
- goto Exit;
-
- zone->max_contours = newContours;
- }
-
- Exit:
- return error;
- }
-
-
-
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
/* TT_Init_Face */
/* */
/* <Description> */
@@ -201,7 +142,7 @@
/* face :: The newly built face object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error TT_Init_Face( FT_Stream stream,
@@ -211,18 +152,13 @@
FT_Parameter* params )
{
FT_Error error;
- FT_Driver sfnt_driver;
+ FT_Library library;
SFNT_Interface* sfnt;
+ library = face->root.driver->root.library;
+ sfnt = (SFNT_Interface*)FT_Get_Module_Interface( library, "sfnt" );
+ if (!sfnt) goto Bad_Format;
- 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;
@@ -320,7 +256,7 @@
/* size :: A handle to the size object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_DEF
FT_Error TT_Init_Size( TT_Size size )
@@ -396,7 +332,7 @@
/* set `face->interpreter' according to the debug hook present */
{
- FT_Library library = face->root.driver->library;
+ FT_Library library = face->root.driver->root.library;
face->interpreter = (TT_Interpreter)
@@ -697,67 +633,10 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* TT_Init_GlyphSlot */
- /* */
- /* <Description> */
- /* The TrueType glyph slot initializer. */
- /* */
- /* <Input> */
- /* slot :: The glyph record to build. */
- /* */
- /* <Output> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error TT_Init_GlyphSlot( TT_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 TrueType glyph slot finalizer. */
- /* */
- /* <Input> */
- /* slot :: A handle to the glyph slot object. */
- /* */
- LOCAL_FUNC
- void TT_Done_GlyphSlot( TT_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> */
/* TT_Init_Driver */
/* */
/* <Description> */
@@ -767,25 +646,24 @@
/* driver :: A handle to the target driver object. */
/* */
/* <Return> */
- /* FreeType error code. 0 means success. */
+ /* TrueType error code. 0 means success. */
/* */
LOCAL_FUNC
FT_Error TT_Init_Driver( TT_Driver driver )
{
- FT_Memory memory = driver->root.memory;
FT_Error error;
- error = TT_New_GlyphZone( memory, 0, 0, &driver->zone );
- if ( error )
- return error;
-
+ /* set 'extra' in glyph loader */
+ error = FT_GlyphLoader_Create_Extra( FT_DRIVER(driver)->glyph_loader );
+
/* init extension registry if needed */
#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
- return TT_Init_Extensions( driver );
-#else
- return TT_Err_Ok;
+ if (!error)
+ return TT_Init_Extensions( driver );
#endif
+
+ return error;
}
@@ -809,15 +687,12 @@
TT_Done_Extensions( driver );
#endif
- /* remove the loading glyph zone */
- TT_Done_GlyphZone( &driver->zone );
-
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
/* destroy the execution context */
if ( driver->context )
{
- TT_Destroy_Context( driver->context, driver->root.memory );
+ TT_Destroy_Context( driver->context, driver->root.root.memory );
driver->context = NULL;
}
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -151,10 +151,6 @@
FT_Short maxContours,
TT_GlyphZone* zone );
- LOCAL_DEF FT_Error TT_Update_GlyphZone( TT_GlyphZone* zone,
- FT_UShort newPoints,
- FT_Short newContours );
-
/*************************************************************************/
/* */
/* EXECUTION SUBTABLES */
@@ -440,17 +436,6 @@
LOCAL_DEF
FT_Error TT_Reset_Size( TT_Size size );
-
-
- /*************************************************************************/
- /* */
- /* GlyphSlot functions */
- /* */
- LOCAL_DEF
- FT_Error TT_Init_GlyphSlot( TT_GlyphSlot slot );
-
- LOCAL_DEF
- void TT_Done_GlyphSlot( TT_GlyphSlot slot );
/*************************************************************************/
--- a/src/type1/module.mk
+++ b/src/type1/module.mk
@@ -1,6 +1,6 @@
make_module_list: add_type1_driver
add_type1_driver:
- $(OPEN_DRIVER)t1_driver_interface$(CLOSE_DRIVER)
+ $(OPEN_DRIVER)t1_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)type1 $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
--- a/src/type1/t1afm.h
+++ b/src/type1/t1afm.h
@@ -1,59 +1,47 @@
-/***************************************************************************/
-/* */
-/* t1afm.h */
-/* */
-/* AFM support for Type 1 fonts (specification). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/***************************************************************************
+ *
+ * t1afm.h - support for reading Type 1 AFM files
+ *
+ *
+ ***************************************************************************/
-
#ifndef T1AFM_H
#define T1AFM_H
#include <freetype/internal/ftobjs.h>
+/* In this version, we only read the kerning table from the */
+/* AFM file. We may add support for ligatures a bit later.. */
- typedef struct T1_Kern_Pair_
- {
- FT_UInt glyph1;
- FT_UInt glyph2;
- FT_Vector kerning;
+typedef struct T1_Kern_Pair_
+{
+ FT_UInt glyph1;
+ FT_UInt glyph2;
+ FT_Vector kerning;
- } T1_Kern_Pair;
+} T1_Kern_Pair;
- typedef struct T1_AFM_
- {
- FT_Int num_pairs;
- T1_Kern_Pair* kern_pairs;
- } T1_AFM;
+typedef struct T1_AFM_
+{
+ FT_Int num_pairs;
+ T1_Kern_Pair* kern_pairs;
+} T1_AFM;
- LOCAL_DEF
- FT_Error T1_Read_AFM( FT_Face face,
- FT_Stream stream );
- LOCAL_DEF
- void T1_Done_AFM( FT_Memory memory,
- T1_AFM* afm );
+LOCAL_DEF
+FT_Error T1_Read_AFM( FT_Face face,
+ FT_Stream stream );
- LOCAL_DEF
- void T1_Get_Kerning( T1_AFM* afm,
- FT_UInt glyph1,
- FT_UInt glyph2,
- FT_Vector* kerning );
+LOCAL_DEF
+void T1_Done_AFM( FT_Memory memory,
+ T1_AFM* afm );
+LOCAL_DEF
+void T1_Get_Kerning( T1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
#endif /* T1AFM_H */
-
-
-/* END */
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -1,21 +1,20 @@
-/***************************************************************************/
-/* */
-/* t1driver.c */
-/* */
-/* Type 1 driver interface (body). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/*******************************************************************
+ *
+ * t1driver.c
+ *
+ * High-level Type1 driver interface for FreeType 2.0
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
-
#include <t1driver.h>
#include <t1gload.h>
#include <t1afm.h>
@@ -24,64 +23,14 @@
#include <freetype/internal/ftstream.h>
#include <freetype/internal/psnames.h>
-
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_t1driver
-
#ifndef T1_CONFIG_OPTION_NO_AFM
-
/*************************************************************************/
/* */
/* <Function> */
- /* Get_Interface */
- /* */
- /* <Description> */
- /* Each driver can provide one or more extensions to the base */
- /* FreeType API. These can be used to access format specific */
- /* features (e.g., all TrueType/OpenType resources share a common */
- /* file structure and common tables which can be accessed through the */
- /* `sfnt' interface), or more simply generic ones (e.g., the */
- /* `postscript names' interface which can be used to retrieve the */
- /* PostScript name of a given glyph index). */
- /* */
- /* <InOut> */
- /* driver :: A handle to a driver object. */
- /* */
- /* <Input> */
- /* interface :: A string designing the interface. Examples are */
- /* `sfnt', `post_names', `charmaps', etc. */
- /* */
- /* <Return> */
- /* A typeless pointer to the extension's interface (normally a table */
- /* of function pointers). Returns NULL if the requested extension */
- /* isn't available (i.e., wasn't compiled in the driver at build */
- /* time). */
- /* */
- static
- FTDriver_Interface Get_Interface( FT_Driver driver,
- const FT_String* interface )
- {
- UNUSED( driver );
-
- if ( strcmp( (const char*)interface, "attach_file" ) == 0 )
- return (FTDriver_Interface)T1_Read_AFM;
-
- return 0;
- }
-
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
/* Get_Kerning */
/* */
/* <Description> */
@@ -119,58 +68,44 @@
{
T1_AFM* afm;
-
kerning->x = 0;
kerning->y = 0;
afm = (T1_AFM*)face->afm_data;
- if ( afm )
+ if (afm)
T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
return T1_Err_Ok;
}
+#endif
-
-#endif /* !T1_CONFIG_OPTION_NO_AFM */
-
-
- /*************************************************************************/
- /* */
- /* <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. */
- /* */
- /* horz_resolution :: The horizontal resolution of the output device. */
- /* */
- /* vert_resolution :: The vertical resolution of the output device. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+ /******************************************************************/
+ /* */
+ /* <Function> Set_Char_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes */
+ /* (horizontal and vertical) expressed in fractional points. */
+ /* */
+ /* <Input> */
+ /* size :: handle to target size object */
+ /* char_width :: character width expressed in 26.6 points */
+ /* char_height :: character height expressed in 26.6 points */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success */
+ /* */
static
- FT_Error Set_Char_Sizes( T1_Size size,
- FT_F26Dot6 char_width,
- FT_F26Dot6 char_height,
- FT_UInt horz_resolution,
- FT_UInt vert_resolution )
+ FT_Error Set_Char_Sizes( T1_Size size,
+ FT_F26Dot6 char_width,
+ FT_F26Dot6 char_height,
+ FT_UInt horz_resolution,
+ FT_UInt vert_resolution )
{
- UNUSED( char_width );
- UNUSED( char_height );
- UNUSED( horz_resolution );
- UNUSED( vert_resolution );
+ UNUSED(char_width);
+ UNUSED(char_height);
+ UNUSED(horz_resolution);
+ UNUSED(vert_resolution);
size->valid = FALSE;
return T1_Reset_Size( size );
@@ -177,39 +112,43 @@
}
- /*************************************************************************/
- /* */
- /* <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. */
- /* */
+ /******************************************************************/
+ /* */
+ /* <Function> Set_Pixel_Sizes */
+ /* */
+ /* <Description> */
+ /* A driver method used to reset a size's character sizes */
+ /* (horizontal and vertical) expressed in integer pixels. */
+ /* */
+ /* <Input> */
+ /* size :: handle to target size object */
+ /* */
+ /* pixel_width :: character width expressed in 26.6 points */
+ /* */
+ /* pixel_height :: character height expressed in 26.6 points */
+ /* */
+ /* char_size :: the corresponding character size in points */
+ /* This value is only sent to the TrueType */
+ /* bytecode interpreter, even though 99% of */
+ /* glyph programs will simply ignore it. A */
+ /* safe value there is the maximum of the */
+ /* pixel width and height (multiplied by */
+ /* 64 to make it a 26.6 fixed float !) */
+ /* <Return> */
+ /* FreeType error code. 0 means success */
+ /* */
static
- FT_Error Set_Pixel_Sizes( T1_Size size,
- FT_Int pixel_width,
- FT_Int pixel_height )
+ FT_Error Set_Pixel_Sizes( T1_Size size,
+ FT_Int pixel_width,
+ FT_Int pixel_height )
{
- UNUSED( pixel_width );
- UNUSED( pixel_height );
+ UNUSED(pixel_width);
+ UNUSED(pixel_height);
size->valid = FALSE;
- return T1_Reset_Size( size );
+ return T1_Reset_Size(size);
}
-
/*************************************************************************/
/* */
/* <Function> */
@@ -233,155 +172,155 @@
FT_UInt result = 0;
PSNames_Interface* psnames;
-
face = (T1_Face)charmap->face;
psnames = (PSNames_Interface*)face->psnames;
- if ( psnames )
- switch ( charmap->encoding )
+ if (psnames)
+ switch (charmap->encoding)
{
- /*******************************************************************/
- /* */
- /* Unicode encoding support */
- /* */
- case ft_encoding_unicode:
- /* use the `PSNames' module to synthetize the Unicode charmap */
- result = psnames->lookup_unicode( &face->unicode_map,
- (FT_ULong)charcode );
+ /********************************************************************/
+ /* */
+ /* Unicode encoding support */
+ /* */
+ case ft_encoding_unicode:
+ {
+ /* use the "psnames" module to synthetize the Unicode charmap */
+ result = psnames->lookup_unicode( &face->unicode_map,
+ (FT_ULong)charcode );
- /* the function returns 0xFFFF if the Unicode charcode has */
- /* no corresponding glyph. */
- if ( result == 0xFFFF )
- result = 0;
- goto Exit;
+ /* the function returns 0xFFFF when the Unicode charcode has */
+ /* no corresponding glyph.. */
+ if (result == 0xFFFF)
+ result = 0;
+ goto Exit;
+ }
- /*******************************************************************/
- /* */
- /* Custom Type 1 encoding */
- /* */
- case ft_encoding_adobe_custom:
- {
- T1_Encoding* encoding = &face->type1.encoding;
+ /********************************************************************/
+ /* */
+ /* Custom Type 1 encoding */
+ /* */
+ case ft_encoding_adobe_custom:
+ {
+ T1_Encoding* encoding = &face->type1.encoding;
+ if (charcode >= encoding->code_first &&
+ charcode <= encoding->code_last)
+ {
+ result = encoding->char_index[charcode];
+ }
+ goto Exit;
+ }
+ /********************************************************************/
+ /* */
+ /* Adobe Standard & Expert encoding support */
+ /* */
+ default:
+ if (charcode < 256)
+ {
+ FT_UInt code;
+ FT_Int n;
+ const char* glyph_name;
- if ( charcode >= encoding->code_first &&
- charcode <= encoding->code_last )
- result = encoding->char_index[charcode];
- goto Exit;
- }
+ code = psnames->adobe_std_encoding[charcode];
+ if (charmap->encoding == ft_encoding_adobe_expert)
+ code = psnames->adobe_expert_encoding[charcode];
- /*******************************************************************/
- /* */
- /* Adobe Standard & Expert encoding support */
- /* */
- default:
- if ( charcode < 256 )
- {
- FT_UInt code;
- FT_Int n;
- const char* glyph_name;
+ glyph_name = psnames->adobe_std_strings(code);
+ if (!glyph_name) break;
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ const char* gname = face->type1.glyph_names[n];
- code = psnames->adobe_std_encoding[charcode];
- if ( charmap->encoding == ft_encoding_adobe_expert )
- code = psnames->adobe_expert_encoding[charcode];
-
- glyph_name = psnames->adobe_std_strings( code );
- if ( !glyph_name )
- break;
-
- for ( n = 0; n < face->type1.num_glyphs; n++ )
- {
- const char* gname = face->type1.glyph_names[n];
-
-
- if ( gname && gname[0] == glyph_name[0] &&
- strcmp( gname, glyph_name ) == 0 )
- {
- result = n;
- break;
- }
- }
- }
+ if ( gname && gname[0] == glyph_name[0] &&
+ strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
}
-
Exit:
return result;
}
- const FT_DriverInterface t1_driver_interface =
+
+
+ const FT_Driver_Class t1_driver_class =
{
- sizeof( FT_DriverRec ),
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1", /* driver name */
+ 0x10000, /* driver version 1.0 */
+ 0x20000, /* driver requires FreeType 2.0 or above */
+
+ 0, /* module specific interface */
+
+ (FT_Module_Constructor) 0,
+ (FT_Module_Destructor) 0,
+#ifdef T1_CONFIG_OPTION_NO_AFM
+ (FT_Module_Requester) Get_Interface
+#else
+ (FT_Module_Requester) 0
+#endif
+ },
+
sizeof( T1_FaceRec ),
sizeof( T1_SizeRec ),
sizeof( T1_GlyphSlotRec ),
- "type1",
- 100,
- 200,
+ (FTDriver_initFace) T1_Init_Face,
+ (FTDriver_doneFace) T1_Done_Face,
+ (FTDriver_initSize) T1_Init_Size,
+ (FTDriver_doneSize) T1_Done_Size,
+ (FTDriver_initGlyphSlot) T1_Init_GlyphSlot,
+ (FTDriver_doneGlyphSlot) T1_Done_GlyphSlot,
- 0, /* format interface */
+ (FTDriver_setCharSizes) Set_Char_Sizes,
+ (FTDriver_setPixelSizes) Set_Pixel_Sizes,
+ (FTDriver_loadGlyph) T1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
- (FTDriver_initDriver) T1_Init_Driver,
- (FTDriver_doneDriver) T1_Done_Driver,
-
#ifdef T1_CONFIG_OPTION_NO_AFM
- (FTDriver_getInterface) 0,
+ (FTDriver_getKerning) 0,
+ (FTDriver_getAdvances) 0
#else
- (FTDriver_getInterface) Get_Interface,
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) T1_Read_AFM
#endif
-
- (FTDriver_initFace) T1_Init_Face,
- (FTDriver_doneFace) T1_Done_Face,
-
-#ifdef T1_CONFIG_OPTION_NO_AFM
- (FTDriver_getKerning) 0,
-#else
- (FTDriver_getKerning) Get_Kerning,
-#endif
-
- (FTDriver_initSize) T1_Init_Size,
- (FTDriver_doneSize) T1_Done_Size,
- (FTDriver_setCharSizes) Set_Char_Sizes,
- (FTDriver_setPixelSizes)Set_Pixel_Sizes,
-
- (FTDriver_initGlyphSlot)T1_Init_GlyphSlot,
- (FTDriver_doneGlyphSlot)T1_Done_GlyphSlot,
- (FTDriver_loadGlyph) T1_Load_Glyph,
-
- (FTDriver_getCharIndex) Get_Char_Index,
};
+ /******************************************************************/
+ /* */
+ /* <Function> Get_FreeType_Driver_Interface */
+ /* */
+ /* <Description> */
+ /* This function is used when compiling the TrueType driver */
+ /* as a shared library (.DLL or .so). It will be used by the */
+ /* high-level library of FreeType to retrieve the address of */
+ /* the driver's generic interface. */
+ /* */
+ /* It shouldn't be implemented in a static build, as each */
+ /* driver must have the same function as an exported entry */
+ /* point. */
+ /* */
+ /* <Return> */
+ /* address of TrueType's driver generic interface. The */
+ /* forma-specific interface can then be retrieved through */
+ /* the method interface->get_format_interface.. */
+ /* */
+
#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* getDriverInterface */
- /* */
- /* <Description> */
- /* This function is used when compiling the CID 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 CID's driver generic interface. The */
- /* format-specific interface can then be retrieved through the method */
- /* interface->get_format_interface. */
- /* */
- EXPORT_FUNC( FT_DriverInterface* ) getDriverInterface( void )
+ EXPORT_FUNC(const FT_Driver_Class*) getDriverClass( void )
{
- return &t1_driver_interface;
+ return &t1_driver_class;
}
-
#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
-/* END */
--- a/src/type1/t1driver.h
+++ b/src/type1/t1driver.h
@@ -1,30 +1,26 @@
-/***************************************************************************/
-/* */
-/* t1driver.h */
-/* */
-/* High-level Type 1 driver interface (specification). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/*******************************************************************
+ *
+ * t1driver.h
+ *
+ * High-level Type1 driver interface for FreeType 2.0
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
-
#ifndef T1DRIVER_H
#define T1DRIVER_H
-#include <t1objs.h>
-#include <freetype/internal/t1errors.h>
+#include <freetype/internal/ftdriver.h>
- FT_EXPORT_VAR( const FT_DriverInterface ) t1_driver_interface;
+ FT_EXPORT_VAR(const FT_Driver_Class) t1_driver_class;
#endif /* T1DRIVER_H */
-
-/* END */
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -1,21 +1,20 @@
-/***************************************************************************/
-/* */
-/* t1gload.c */
-/* */
-/* Type 1 Glyph Loader (body). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/*******************************************************************
+ *
+ * t1gload.c 1.0
+ *
+ * Type1 Glyph Loader.
+ *
+ * Copyright 1996-1999 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
-
#include <t1gload.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
@@ -24,33 +23,37 @@
#include <t1hinter.h>
#endif
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** GENERIC CHARSTRINGS PARSING *********/
+ /********** *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
-#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1gload
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Init_Builder
+ *
+ * <Description>
+ * Initialise a given glyph builder.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ * face :: current face object
+ * size :: current size object
+ * glyph :: current glyph object
+ * funcs :: glyph builder functions (or "methods").
+ *
+ *********************************************************************/
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** *********/
- /********** GENERIC CHARSTRING PARSING *********/
- /********** *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
static
- void T1_Reset_Builder( T1_Builder* builder,
- FT_Bool reset_base )
+ void T1_Reset_Builder( T1_Builder* builder, FT_Bool reset_base )
{
builder->pos_x = 0;
builder->pos_y = 0;
@@ -63,52 +66,22 @@
builder->pass = 0;
builder->hint_point = 0;
- if ( reset_base )
+ if (builder->loader)
{
- builder->base.n_points = 0;
- builder->base.n_contours = 0;
- }
+ if (reset_base)
+ FT_GlyphLoader_Rewind( builder->loader );
- {
- FT_Outline* base = &builder->base;
- FT_Outline* cur = &builder->current;
-
-
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
+ FT_GlyphLoader_Prepare( builder->loader );
}
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Init_Builder */
- /* */
- /* <Description> */
- /* Initializes a given glyph builder. */
- /* */
- /* <InOut> */
- /* builder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph object. */
- /* */
- /* funcs :: Glyph builder functions (or `methods'). */
- /* */
LOCAL_FUNC
- void T1_Init_Builder( T1_Builder* builder,
- T1_Face face,
- T1_Size size,
- T1_GlyphSlot glyph,
- const T1_Builder_Funcs* funcs )
+ void T1_Init_Builder( T1_Builder* builder,
+ T1_Face face,
+ T1_Size size,
+ T1_GlyphSlot glyph,
+ const T1_Builder_Funcs* funcs )
{
builder->funcs = *funcs;
builder->path_begun = 0;
@@ -119,14 +92,16 @@
builder->glyph = glyph;
builder->memory = face->root.memory;
- if ( glyph )
+ if (glyph)
{
- builder->base = glyph->root.outline;
- builder->max_points = glyph->max_points;
- builder->max_contours = glyph->max_contours;
+ FT_GlyphLoader* loader = FT_SLOT(glyph)->loader;
+
+ builder->loader = loader;
+ builder->base = &loader->base.outline;
+ builder->current = &loader->current.outline;
}
- if ( size )
+ if (size)
{
builder->scale_x = size->root.metrics.x_scale;
builder->scale_y = size->root.metrics.y_scale;
@@ -136,47 +111,47 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Done_Builder */
- /* */
- /* <Description> */
- /* Finalizes a given glyph builder. Its contents can still be used */
- /* after the call, but the function saves important information */
- /* within the corresponding glyph slot. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder to finalize. */
- /* */
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Done_Builder
+ *
+ * <Description>
+ * Finalise a given glyph builder. Its content can still be
+ * used after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ *
+ *********************************************************************/
+
LOCAL_FUNC
- void T1_Done_Builder( T1_Builder* builder )
+ void T1_Done_Builder( T1_Builder* builder )
{
T1_GlyphSlot glyph = builder->glyph;
-
- if ( glyph )
- {
- glyph->root.outline = builder->base;
- glyph->max_points = builder->max_points;
- glyph->max_contours = builder->max_contours;
- }
+ if (glyph)
+ glyph->root.outline = *builder->base;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Init_Decoder */
- /* */
- /* <Description> */
- /* Initializes a given glyph decoder. */
- /* */
- /* <InOut> */
- /* decoder :: A pointer to the glyph builder to initialize. */
- /* */
- /* <Input> */
- /* funcs :: The hinting functions interface. */
+
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Init_Decoder
+ *
+ * <Description>
+ * Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ * decoder :: Type 1 decoder to initialise
+ * funcs :: hinter functions interface
+ *
+ *********************************************************************/
+
+
LOCAL_FUNC
void T1_Init_Decoder( T1_Decoder* decoder,
const T1_Hinter_Funcs* funcs )
@@ -189,50 +164,49 @@
decoder->num_flex_vectors = 0;
/* Clear loader */
- MEM_Set( &decoder->builder, 0, sizeof ( decoder->builder ) );
+ MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* lookup_glyph_by_stdcharcode */
- /* */
- /* <Description> */
- /* Looks up a given glyph by its StandardEncoding charcode. Used */
- /* to implement the SEAC Type 1 operator. */
- /* */
- /* <Input> */
- /* face :: The current face object. */
- /* */
- /* charcode :: The character code to look for. */
- /* */
- /* <Return> */
- /* A glyph index in the font face. Returns -1 if the corresponding */
- /* glyph wasn't found. */
- /* */
+/*********************************************************************
+ *
+ * <Function>
+ * lookup_glyph_by_stdcharcode
+ *
+ * <Description>
+ * Lookup a given glyph by its StandardEncoding charcode. Used
+ * to implement the SEAC Type 1 operator.
+ *
+ * <Input>
+ * face :: current face object
+ * charcode :: charcode to look for
+ *
+ * <Return>
+ * glyph index in font face. Returns -1 if the corresponding
+ * glyph wasn't found.
+ *
+ *********************************************************************/
+
static
- FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
- FT_Int charcode )
+ FT_Int lookup_glyph_by_stdcharcode( T1_Face face,
+ FT_Int charcode )
{
FT_Int n;
const FT_String* glyph_name;
PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
-
/* check range of standard char code */
- if ( charcode < 0 || charcode > 255 )
+ if (charcode < 0 || charcode > 255)
return -1;
glyph_name = psnames->adobe_std_strings(
- psnames->adobe_std_encoding[charcode]);
+ psnames->adobe_std_encoding[charcode]);
for ( n = 0; n < face->type1.num_glyphs; n++ )
{
FT_String* name = (FT_String*)face->type1.glyph_names[n];
-
- if ( name && strcmp( name, glyph_name ) == 0 )
+ if ( name && strcmp(name,glyph_name) == 0 )
return n;
}
@@ -240,30 +214,27 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1operator_seac */
- /* */
- /* <Description> */
- /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
- /* */
- /* <Input> */
- /* decoder :: The current CID decoder. */
- /* */
- /* asb :: The accent's side bearing. */
- /* */
- /* adx :: The horizontal offset of the accent. */
- /* */
- /* ady :: The vertical offset of the accent. */
- /* */
- /* bchar :: The base character's StandardEncoding charcode. */
- /* */
- /* achar :: The accent character's StandardEncoding charcode. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+/*********************************************************************
+ *
+ * <Function>
+ * t1operator_seac
+ *
+ * <Description>
+ * Implements the "seac" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * asb :: accent's side bearing
+ * adx :: horizontal position of accent
+ * ady :: vertical position of accent
+ * bchar :: base character's StandardEncoding charcode
+ * achar :: accent character's StandardEncoding charcode
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
+
static
FT_Error t1operator_seac( T1_Decoder* decoder,
FT_Pos asb,
@@ -273,14 +244,13 @@
FT_Int achar )
{
FT_Error error;
- T1_Face face = decoder->builder.face;
FT_Int bchar_index, achar_index, n_base_points;
- FT_Outline* cur = &decoder->builder.current;
- FT_Outline* base = &decoder->builder.base;
+ FT_Outline* cur = decoder->builder.current;
+ FT_Outline* base = decoder->builder.base;
FT_Vector left_bearing, advance;
+ T1_Face face = decoder->builder.face;
T1_Font* type1 = &face->type1;
-
bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
achar_index = lookup_glyph_by_stdcharcode( face, achar );
@@ -290,30 +260,21 @@
return T1_Err_Syntax_Error;
}
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
if ( decoder->builder.no_recurse )
{
- /* if we are trying to load a composite glyph, do not load the */
- /* accent character and return the array of subglyphs. */
- FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
- FT_SubGlyph* subg;
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
-
/* reallocate subglyph array if necessary */
- if ( glyph->max_subglyphs < 2 )
- {
- FT_Memory memory = decoder->builder.face->root.memory;
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if (error) goto Exit;
+
+ subg = loader->current.subglyphs;
-
- if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
- 2, FT_SubGlyph ) )
- return error;
-
- glyph->max_subglyphs = 2;
- }
-
- subg = glyph->subglyphs;
-
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
@@ -331,29 +292,27 @@
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
}
- else
- {
- /* First load `bchar' in builder */
- /* now load the unscaled outline */
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
-
- error = T1_Parse_CharStrings( decoder,
- type1->charstrings [bchar_index],
- type1->charstrings_len[bchar_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
- if ( error )
- return error;
-
- n_base_points = cur->n_points;
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ if (decoder->builder.loader)
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [bchar_index],
+ type1->charstrings_len[bchar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error ) goto Exit;
+
+ n_base_points = cur->n_points;
+
+ {
/* save the left bearing and width of the base character */
/* as they will be erased by the next load. */
@@ -365,13 +324,6 @@
/* Now load `achar' on top of */
/* the base outline */
-
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
-
error = T1_Parse_CharStrings( decoder,
type1->charstrings [achar_index],
type1->charstrings_len[achar_index],
@@ -378,17 +330,8 @@
type1->num_subrs,
type1->subrs,
type1->subrs_len );
- if ( error )
- return error;
+ if ( error ) return error;
- /* adjust contours in accented character outline */
- {
- FT_Int n;
-
- for ( n = 0; n < cur->n_contours; n++ )
- cur->contours[n] += n_base_points;
- }
-
/* restore the left side bearing and */
/* advance width of the base character */
@@ -396,30 +339,38 @@
decoder->builder.advance = advance;
/* Finally, move the accent */
- FT_Outline_Translate( cur, adx - asb, ady );
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
}
-
- return T1_Err_Ok;
+ Exit:
+ return error;
}
+/*********************************************************************
+ *
+ * <Function>
+ * t1operator_flex
+ *
+ * <Description>
+ * Implements the "flex" Type 1 operator for a Type 1 decoder
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * threshold :: threshold
+ * end_x :: position of final flex point
+ * end_y :: position of final flex point
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1operator_flex */
- /* */
- /* <Description> */
- /* Implements the `flex' Type 1 operator for a Type 1 decoder. */
- /* */
- /* <Input> */
- /* decoder :: The current Type 1 decoder. */
- /* threshold :: The threshold. */
- /* end_x :: The horizontal position of the final flex point. */
- /* end_y :: The vertical position of the final flex point. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
static
FT_Error t1operator_flex( T1_Decoder* decoder,
FT_Pos threshold,
@@ -430,15 +381,10 @@
FT_Vector* flex = decoder->flex_vectors;
FT_Int n;
- UNUSED( threshold );
- UNUSED( end_x );
- UNUSED( end_y );
-
-
- /* we don't even try to test the threshold in the non-hinting */
+ /* we don't even try to test the threshold in the non-hinting */
/* builder, even if the flex operator is said to be a path */
- /* construction statement in the specification. This is better */
- /* left to the hinter. */
+ /* construction statement in the specification. This is better */
+ /* left to the hinter.. */
flex = decoder->flex_vectors;
vec = *flex++;
@@ -451,6 +397,11 @@
vec = *flex++;
}
+
+ UNUSED(threshold);
+ UNUSED(end_x);
+ UNUSED(end_y);
+
flex = decoder->flex_vectors;
return decoder->builder.funcs.rcurve_to( &decoder->builder,
@@ -465,37 +416,34 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Parse_CharStrings */
- /* */
- /* <Description> */
- /* Parses a given Type 1 charstrings program. */
- /* */
- /* <Input> */
- /* decoder :: The current Type 1 decoder. */
- /* */
- /* charstring_base :: The base address of the charstring stream. */
- /* */
- /* charstring_len :: The length in bytes of the charstring stream. */
- /* */
- /* num_subrs :: The number of sub-routines. */
- /* */
- /* subrs_base :: An array of sub-routines addresses. */
- /* */
- /* subrs_len :: An array of sub-routines lengths. */
- /* */
- /* <Return> */
- /* Free error code. 0 means success. */
- /* */
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Parse_CharStrings
+ *
+ * <Description>
+ * Parses a given Type 1 charstrings program
+ *
+ * <Input>
+ * decoder :: current Type 1 decoder
+ * charstring_base :: base of the charstring stream
+ * charstring_len :: length in bytes of the charstring stream
+ * num_subrs :: number of sub-routines
+ * subrs_base :: array of sub-routines addresses
+ * subrs_len :: array of sub-routines lengths
+ *
+ * <Return>
+ * Error code. 0 means success.
+ *
+ *********************************************************************/
+
LOCAL_FUNC
- FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_Int charstring_len,
- FT_Int num_subrs,
- FT_Byte** subrs_base,
- FT_Int* subrs_len )
+ FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len )
{
FT_Error error;
T1_Decoder_Zone* zone;
@@ -505,7 +453,7 @@
T1_Builder_Funcs* builds = &builder->funcs;
T1_Hinter_Funcs* hints = &decoder->hinter;
- static const FT_Int args_count[op_max] =
+ static const FT_Int args_count[ op_max ] =
{
0, /* none */
0, /* endchar */
@@ -535,8 +483,7 @@
2 /* setcurrentpoint */
};
-
- /* First of all, initialize the decoder */
+ /* First of all, initialise the decoder */
decoder->top = decoder->stack;
decoder->zone = decoder->zones;
zone = decoder->zones;
@@ -556,146 +503,99 @@
T1_Operator op = op_none;
FT_Long value = 0;
-
- /* Start with the decompression of operator or value */
- switch ( *ip++ )
+ /* First of all, decompress operator or value */
+ switch (*ip++)
{
- case 1:
- op = op_hstem;
- break;
+ case 1: op = op_hstem; break;
- case 3:
- op = op_vstem;
- break;
- case 4:
- op = op_vmoveto;
- break;
- case 5:
- op = op_rlineto;
- break;
- case 6:
- op = op_hlineto;
- break;
- case 7:
- op = op_vlineto;
- break;
- case 8:
- op = op_rrcurveto;
- break;
- case 9:
- op = op_closepath;
- break;
- case 10:
- op = op_callsubr;
- break;
- case 11:
- op = op_return;
- break;
+ case 3: op = op_vstem; break;
+ case 4: op = op_vmoveto; break;
+ case 5: op = op_rlineto; break;
+ case 6: op = op_hlineto; break;
+ case 7: op = op_vlineto; break;
+ case 8: op = op_rrcurveto; break;
+ case 9: op = op_closepath; break;
+ case 10: op = op_callsubr; break;
+ case 11: op = op_return; break;
- case 13:
- op = op_hsbw;
- break;
- case 14:
- op = op_endchar;
- break;
+ case 13: op = op_hsbw; break;
+ case 14: op = op_endchar; break;
- case 21:
- op = op_rmoveto;
- break;
- case 22:
- op = op_hmoveto;
- break;
+ case 21: op = op_rmoveto; break;
+ case 22: op = op_hmoveto; break;
- case 30:
- op = op_vhcurveto;
- break;
- case 31:
- op = op_hvcurveto;
- break;
+ case 30: op = op_vhcurveto; break;
+ case 31: op = op_hvcurveto; break;
- case 12:
- if ( ip > limit )
- {
- FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+EOF)\n" ));
- goto Syntax_Error;
- }
-
- switch ( *ip++ )
- {
- case 0:
- op = op_dotsection;
- break;
- case 1:
- op = op_vstem3;
- break;
- case 2:
- op = op_hstem3;
- break;
- case 6:
- op = op_seac;
- break;
- case 7:
- op = op_sbw;
- break;
case 12:
- op = op_div;
- break;
- case 16:
- op = op_callothersubr;
- break;
- case 17:
- op = op_pop;
- break;
- case 33:
- op = op_setcurrentpoint;
- break;
+ {
+ if (ip > limit)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" ));
+ goto Syntax_Error;
+ }
- default:
- FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
- ip[-1] ));
- goto Syntax_Error;
- }
- break;
+ switch (*ip++)
+ {
+ case 0: op = op_dotsection; break;
+ case 1: op = op_vstem3; break;
+ case 2: op = op_hstem3; break;
+ case 6: op = op_seac; break;
+ case 7: op = op_sbw; break;
+ case 12: op = op_div; break;
+ case 16: op = op_callothersubr; break;
+ case 17: op = op_pop; break;
+ case 33: op = op_setcurrentpoint; break;
- case 255: /* four bytes integer */
- if ( ip + 4 > limit )
- {
- FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
- goto Syntax_Error;
- }
+ default:
+ FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
+ }
+ break;
- value = ( (FT_Long)ip[0] << 24 ) |
- ( (FT_Long)ip[1] << 16 ) |
- ( (FT_Long)ip[2] << 8 ) |
- ip[3];
- ip += 4;
- break;
-
- default:
- if ( ip[-1] >= 32 )
- {
- if ( ip[-1] < 247 )
- value = (FT_Long)ip[-1] - 139;
- else
+ case 255: /* four bytes integer */
{
- if ( ++ip > limit )
+ if (ip+4 > limit)
{
- FT_ERROR(( "T1_Parse_CharStrings: unexpected EOF in integer\n" ));
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
goto Syntax_Error;
}
- if ( ip[-2] < 251 )
- value = ( (FT_Long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+ value = ((long)ip[0] << 24) |
+ ((long)ip[1] << 16) |
+ ((long)ip[2] << 8) |
+ ip[3];
+ ip += 4;
+ }
+ break;
+
+ default:
+ if (ip[-1] >= 32)
+ {
+ if (ip[-1] < 247)
+ value = (long)ip[-1] - 139;
else
- value = -( ( ( (FT_Long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+ {
+ if (++ip > limit)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
+ goto Syntax_Error;
+ }
+
+ if (ip[-2] < 251)
+ value = ((long)(ip[-2]-247) << 8) + ip[-1] + 108;
+ else
+ value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 );
+ }
}
- }
- else
- {
- FT_ERROR(( "T1_Parse_CharStrings: invalid byte (%d)\n",
+ else
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n",
ip[-1] ));
- goto Syntax_Error;
- }
+ goto Syntax_Error;
+ }
}
/* push value if needed */
@@ -703,7 +603,7 @@
{
if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
{
- FT_ERROR(( "T1_Parse_CharStrings: Stack overflow!\n" ));
+ FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" ));
goto Syntax_Error;
}
@@ -710,113 +610,116 @@
*top++ = value;
decoder->top = top;
}
+
else if ( op == op_callothersubr ) /* check arguments differently */
{
- if ( top - decoder->stack < 2 )
+ if ( top - decoder->stack < 2)
goto Stack_Underflow;
top -= 2;
- switch ( top[1] )
+ switch (top[1])
{
- case 1: /* start flex feature ----------------------------- */
- if ( top[0] != 0 )
- goto Unexpected_OtherSubr;
+ case 1: /* start flex feature ----------------------------- */
+ {
+ if (top[0] != 0) goto Unexpected_OtherSubr;
- decoder->flex_state = 1;
- decoder->num_flex_vectors = 0;
- decoder->flex_vectors[0].x = 0;
- decoder->flex_vectors[0].y = 0;
- break;
+ decoder->flex_state = 1;
+ decoder->num_flex_vectors = 0;
+ decoder->flex_vectors[0].x = 0;
+ decoder->flex_vectors[0].y = 0;
+ }
+ break;
- case 2: /* add flex vector ------------------------------- */
- {
- FT_Int index;
- FT_Vector* flex;
+ case 2: /* add flex vector ------------------------------- */
+ {
+ FT_Int index;
+ FT_Vector* flex;
+ if (top[0] != 0) goto Unexpected_OtherSubr;
- if ( top[0] != 0 )
- goto Unexpected_OtherSubr;
+ top -= 2;
+ if (top < decoder->stack) goto Stack_Underflow;
- top -= 2;
- if ( top < decoder->stack )
- goto Stack_Underflow;
+ index = decoder->num_flex_vectors++;
+ if (index >= 7)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: too many flex vectors !\n" ));
+ goto Syntax_Error;
+ }
- index = decoder->num_flex_vectors++;
- if ( index >= 7 )
- {
- FT_ERROR(( "T1_Parse_CharStrings: too many flex vectors!\n" ));
- goto Syntax_Error;
+ flex = decoder->flex_vectors + index;
+ flex->x += top[0];
+ flex->y += top[1];
+
}
+ break;
- flex = decoder->flex_vectors + index;
- flex->x += top[0];
- flex->y += top[1];
- }
- break;
- case 0: /* end flex feature ------------------------------ */
- if ( decoder->flex_state == 0 ||
- decoder->num_flex_vectors != 7 )
- {
- FT_ERROR(( "T1_Parse_CharStrings: unexpected flex end\n" ));
- goto Syntax_Error;
- }
+ case 0: /* end flex feature ------------------------------ */
+ {
+ if ( decoder->flex_state == 0 ||
+ decoder->num_flex_vectors != 7 )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" ));
+ goto Syntax_Error;
+ }
- if ( top[0] != 3 )
- goto Unexpected_OtherSubr;
+ if (top[0] != 3) goto Unexpected_OtherSubr;
- top -= 3;
- if ( top < decoder->stack )
- goto Stack_Underflow;
+ top -= 3;
+ if (top < decoder->stack) goto Stack_Underflow;
- /* now consume the remaining `pop pop setcurrentpoint' */
- if ( ip + 6 > limit ||
- ip[0] != 12 || ip[1] != 17 || /* pop */
- ip[2] != 12 || ip[3] != 17 || /* pop */
- ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */
- {
- FT_ERROR(( "T1_Parse_CharStrings: invalid flex charstring\n" ));
- goto Syntax_Error;
- }
+ /* now consume the remaining "pop pop setcurrentpoint" */
+ if ( ip+6 > limit ||
+ ip[0] != 12 || ip[1] != 17 || /* pop */
+ ip[2] != 12 || ip[3] != 17 || /* pop */
+ ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" ));
+ goto Syntax_Error;
+ }
- decoder->flex_state = 0;
- decoder->top = top;
+ decoder->flex_state = 0;
+ decoder->top = top;
- error = t1operator_flex( decoder, top[0], top[1], top[2] );
- break;
+ error = t1operator_flex( decoder, top[0], top[1], top[2] );
+ }
+ break;
- case 3: /* change hints ------------------------------------ */
- if ( top[0] != 1 )
- goto Unexpected_OtherSubr;
- /* eat the following `pop' */
- if ( ip + 2 > limit )
- {
- FT_ERROR(( "T1_Parse_CharStrings: invalid escape (12+%d)\n",
- ip[-1] ));
- goto Syntax_Error;
- }
+ case 3: /* change hints ------------------------------------ */
+ {
+ if (top[0] != 1) goto Unexpected_OtherSubr;
- if (ip[0] != 12 || ip[1] != 17)
- {
- FT_ERROR(( "T1_Parse_CharStrings: `pop' expected, found (%d %d)\n",
- ip[0], ip[1] ));
- goto Syntax_Error;
- }
+ /* eat the following "pop" */
+ if (ip+2 > limit)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n",
+ ip[-1] ));
+ goto Syntax_Error;
+ }
- ip += 2;
+ if (ip[0] != 12 || ip[1] != 17)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n",
+ ip[0], ip[1] ));
+ goto Syntax_Error;
+ }
- error = hints->change_hints( builder );
- break;
+ ip += 2;
+ error = hints->change_hints(builder);
+ }
+ break;
- default:
- /* invalid OtherSubrs call */
- Unexpected_OtherSubr:
- FT_ERROR(( "T1_Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
+
+ default:
+ /* invalid OtherSubrs call */
+ Unexpected_OtherSubr:
+ FT_ERROR(( "T1.Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
top[0], top[1] ));
- goto Syntax_Error;
+ goto Syntax_Error;
}
decoder->top = top;
}
@@ -824,176 +727,177 @@
{
FT_Int num_args = args_count[op];
-
if ( top - decoder->stack < num_args )
goto Stack_Underflow;
top -= num_args;
- switch ( op )
+ switch (op)
{
- case op_endchar:
- error = builds->end_char( builder );
- break;
+ case op_endchar:
+ error = builds->end_char( builder );
+ break;
- case op_hsbw:
- error = builds->set_bearing_point( builder, top[0], 0,
- top[1], 0 );
- break;
+ case op_hsbw:
+ error = builds->set_bearing_point( builder, top[0], 0,
+ top[1], 0 );
+ break;
- case op_seac:
- /* return immediately after the processing */
- return t1operator_seac( decoder, top[0], top[1],
- top[2], top[3], top[4] );
+ case op_seac:
+ /* return immediately after the processing */
+ return t1operator_seac( decoder, top[0], top[1],
+ top[2], top[3], top[4] );
- case op_sbw:
- error = builds->set_bearing_point( builder, top[0], top[1],
- top[2], top[3] );
- break;
+ case op_sbw:
+ error = builds->set_bearing_point( builder, top[0], top[1],
+ top[2], top[3] );
+ break;
- case op_closepath:
- error = builds->close_path( builder );
- break;
+ case op_closepath:
+ error = builds->close_path( builder );
+ break;
- case op_hlineto:
- error = builds->rline_to( builder, top[0], 0 );
- break;
+ case op_hlineto:
+ error = builds->rline_to( builder, top[0], 0 );
+ break;
- case op_hmoveto:
- error = builds->rmove_to( builder, top[0], 0 );
- break;
+ case op_hmoveto:
+ error = builds->rmove_to( builder, top[0], 0 );
+ break;
- case op_hvcurveto:
- error = builds->rcurve_to( builder, top[0], 0,
- top[1], top[2],
- 0, top[3] );
- break;
+ case op_hvcurveto:
+ error = builds->rcurve_to( builder, top[0], 0,
+ top[1], top[2],
+ 0, top[3] );
+ break;
- case op_rlineto:
- error = builds->rline_to( builder, top[0], top[1] );
- break;
+ case op_rlineto:
+ error = builds->rline_to( builder, top[0], top[1] );
+ break;
- case op_rmoveto:
- /* ignore operator when in flex mode */
- if ( decoder->flex_state == 0 )
- error = builds->rmove_to( builder, top[0], top[1] );
- else
- top += 2;
- break;
+ case op_rmoveto:
+ /* ignore operator when in flex mode */
+ if (decoder->flex_state == 0)
+ error = builds->rmove_to( builder, top[0], top[1] );
+ else
+ top += 2;
+ break;
- case op_rrcurveto:
- error = builds->rcurve_to( builder, top[0], top[1],
- top[2], top[3],
- top[4], top[5] );
- break;
+ case op_rrcurveto:
+ {
+ error = builds->rcurve_to( builder, top[0], top[1],
+ top[2], top[3],
+ top[4], top[5] );
+ }
+ break;
- case op_vhcurveto:
- error = builds->rcurve_to( builder, 0, top[0],
- top[1], top[2],
- top[3], 0 );
- break;
+ case op_vhcurveto:
+ error = builds->rcurve_to( builder, 0, top[0],
+ top[1], top[2],
+ top[3], 0 );
+ break;
- case op_vlineto:
- error = builds->rline_to( builder, 0, top[0] );
- break;
+ case op_vlineto:
+ error = builds->rline_to( builder, 0, top[0] );
+ break;
- case op_vmoveto:
- error = builds->rmove_to( builder, 0, top[0] );
- break;
+ case op_vmoveto:
+ error = builds->rmove_to( builder, 0, top[0] );
+ break;
- case op_dotsection:
- error = hints->dot_section( builder );
- break;
+ case op_dotsection:
+ error = hints->dot_section( builder );
+ break;
- case op_hstem:
- error = hints->stem( builder, top[0], top[1], 0 );
- break;
+ case op_hstem:
+ error = hints->stem( builder, top[0], top[1], 0 );
+ break;
- case op_hstem3:
- error = hints->stem3( builder, top[0], top[1], top[2],
- top[3], top[4], top[5], 0 );
- break;
+ case op_hstem3:
+ error = hints->stem3( builder, top[0], top[1], top[2],
+ top[3], top[4], top[5], 0 );
+ break;
- case op_vstem:
- error = hints->stem( builder, top[0], top[1], 1 );
- break;
+ case op_vstem:
+ error = hints->stem( builder, top[0], top[1], 1 );
+ break;
- case op_vstem3:
- error = hints->stem3( builder, top[0], top[1], top[2],
- top[3], top[4], top[5], 1 );
- break;
+ case op_vstem3:
+ error = hints->stem3( builder, top[0], top[1], top[2],
+ top[3], top[4], top[5], 1 );
+ break;
- case op_div:
- if ( top[1] )
- *top++ = top[0] / top[1];
- else
- {
- FT_ERROR(( "T1_Parse_CHarStrings: division by 0\n" ));
- goto Syntax_Error;
- }
- break;
-
- case op_callsubr:
- {
- FT_Int index = top[0];
-
-
- if ( index < 0 || index >= num_subrs )
+ case op_div:
+ if (top[1])
+ *top++ = top[0] / top[1];
+ else
{
- FT_ERROR(( "T1_Parse_CharStrings: invalid subrs index\n" ));
+ FT_ERROR(( "T1.Parse_CHarStrings : division by 0\n" ));
goto Syntax_Error;
}
+ break;
- if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ case op_callsubr:
{
- FT_ERROR(( "T1_Parse_CharStrings: too many nested subrs\n" ));
- goto Syntax_Error;
+ FT_Int index = top[0];
+
+ if ( index < 0 || index >= num_subrs )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
+ goto Syntax_Error;
+ }
+
+ if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
+ goto Syntax_Error;
+ }
+
+ zone->cursor = ip; /* save current instruction pointer */
+
+ zone++;
+ zone->base = subrs_base[index];
+ zone->limit = zone->base + subrs_len[index];
+ zone->cursor = zone->base;
+
+ if (!zone->base)
+ {
+ FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
+ goto Syntax_Error;
+ }
+
+ decoder->zone = zone;
+ ip = zone->base;
+ limit = zone->limit;
}
+ break;
- zone->cursor = ip; /* save current instruction pointer */
+ case op_pop:
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" ));
+ goto Syntax_Error;
- zone++;
- zone->base = subrs_base[index];
- zone->limit = zone->base + subrs_len[index];
- zone->cursor = zone->base;
- if ( !zone->base )
+ case op_return:
+ if ( zone <= decoder->zones )
{
- FT_ERROR(( "T1_Parse_CharStrings: invoking empty subrs!\n" ));
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
goto Syntax_Error;
}
- decoder->zone = zone;
- ip = zone->base;
+ zone--;
+ ip = zone->cursor;
limit = zone->limit;
- }
- break;
+ decoder->zone = zone;
+ break;
- case op_pop:
- FT_ERROR(( "T1_Parse_CharStrings: unexpected POP\n" ));
- goto Syntax_Error;
-
- case op_return:
- if ( zone <= decoder->zones )
- {
- FT_ERROR(( "T1_Parse_CharStrings: unexpected return\n" ));
+ case op_setcurrentpoint:
+ FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
goto Syntax_Error;
- }
+ break;
- zone--;
- ip = zone->cursor;
- limit = zone->limit;
- decoder->zone = zone;
- break;
-
- case op_setcurrentpoint:
- FT_ERROR(( "T1_Parse_CharStrings: unexpected `setcurrentpoint'\n" ));
- goto Syntax_Error;
- break;
-
- default:
- FT_ERROR(( "T1_Parse_CharStrings : unhandled opcode %d\n", op ));
- goto Syntax_Error;
+ default:
+ FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
+ goto Syntax_Error;
}
decoder->top = top;
@@ -1010,140 +914,83 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Add_Points */
- /* */
- /* <Description> */
- /* Checks that there is enough room in the current load glyph outline */
- /* to accept `num_points' additional outline points. If not, this */
- /* function grows the load outline's arrays accordingly. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder object. */
- /* */
- /* num_points :: The number of points that will be added later. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function does NOT update the points count in the glyph */
- /* builder. This must be done by the caller itself, after this */
- /* function has been invoked. */
- /* */
+
+/*************************************************************************/
+/* */
+/* <Function> T1_Add_Points */
+/* */
+/* <Description> */
+/* Checks that there is enough room in the current load glyph outline */
+/* to accept "num_points" additional outline points. If not, this */
+/* function grows the load outline's arrays accordingly.. */
+/* */
+/* <Input> */
+/* builder :: pointer to glyph builder object */
+/* num_points :: number of points that will be added later */
+/* */
+/* <Return> */
+/* Type1 error code. 0 means success */
+/* */
+/* <Note> */
+/* This function does NOT update the points count in the glyph builder*/
+/* This must be done by the caller itself, after this function is */
+/* invoked.. */
+/* */
LOCAL_FUNC
FT_Error T1_Add_Points( T1_Builder* builder,
FT_Int num_points )
{
- FT_Int new_points;
-
-
- new_points = builder->base.n_points +
- builder->current.n_points +
- num_points;
-
- if ( new_points > builder->max_points )
- {
- FT_Memory memory = builder->memory;
- FT_Error error;
- FT_Int increment = builder->current.points - builder->base.points;
- FT_Int current = builder->max_points;
-
-
- while ( builder->max_points < new_points )
- builder->max_points += 16;
-
- if ( REALLOC_ARRAY( builder->base.points,
- current, builder->max_points, FT_Vector ) ||
-
- REALLOC_ARRAY( builder->base.tags,
- current, builder->max_points, FT_Byte ) )
- return error;
-
- builder->current.points = builder->base.points + increment;
- builder->current.tags = builder->base.tags + increment;
- }
-
- return T1_Err_Ok;
+ return FT_GlyphLoader_Check_Points( builder->loader, num_points, 0 );
}
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Add_Contours */
- /* */
- /* <Description> */
- /* Checks that there is enough room in the current load glyph outline */
- /* to accept `num_contours' additional contours. If not, this */
- /* function grows the load outline's arrays accordingly. */
- /* */
- /* <Input> */
- /* builder :: A pointer to the glyph builder object. */
- /* */
- /* num_contours :: The number of contours that will be added later. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function does NOT update the contours count in the load glyph */
- /* This must be done by the caller itself, after this function is */
- /* invoked. */
- /* */
+/*************************************************************************/
+/* */
+/* <Function> T1_Add_Contours */
+/* */
+/* <Description> */
+/* Checks that there is enough room in the current load glyph outline */
+/* to accept "num_contours" additional contours. If not, this func */
+/* the load outline's arrays accordingly.. */
+/* */
+/* <Input> */
+/* builder :: pointer to glyph builder object */
+/* num_contours :: number of contours that will be added later */
+/* */
+/* <Return> */
+/* Type1 error code. 0 means success */
+/* */
+/* <Note> */
+/* This function does NOT update the contours count in the load glyph */
+/* This must be done by the caller itself, after this function is */
+/* invoked.. */
+/* */
LOCAL_FUNC
FT_Error T1_Add_Contours( T1_Builder* builder,
FT_Int num_contours )
{
- FT_Int new_contours;
-
-
- new_contours = builder->base.n_contours +
- builder->current.n_contours +
- num_contours;
-
- if ( new_contours > builder->max_contours && builder->load_points )
- {
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = builder->current.contours -
- builder->base.contours;
- FT_Int current = builder->max_contours;
-
-
- while ( builder->max_contours < new_contours )
- builder->max_contours += 4;
-
- if ( REALLOC_ARRAY( builder->base.contours,
- current, builder->max_contours, FT_Short ) )
- return error;
-
- builder->current.contours = builder->base.contours + increment;
- }
-
- return T1_Err_Ok;
+ return FT_GlyphLoader_Check_Points( builder->loader, 0, num_contours );
}
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
- /********** *********/
- /********** The following code is in charge of computing *********/
- /********** the maximum advance width of the font. It *********/
- /********** quickly processes each glyph charstring to *********/
- /********** extract the value from either a `sbw' or `seac' *********/
- /********** operator. *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the maximum advance width of the font. It *********/
+ /********** quickly process each glyph charstring to *********/
+ /********** extract the value from either a "sbw" or "seac" *********/
+ /********** operator. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+
static
FT_Error maxadv_sbw( T1_Decoder* decoder,
FT_Pos sbx,
@@ -1151,13 +998,12 @@
FT_Pos wx,
FT_Pos wy )
{
- UNUSED( sbx );
- UNUSED( sby );
- UNUSED( wy );
-
- if ( wx > decoder->builder.advance.x )
+ if (wx > decoder->builder.advance.x)
decoder->builder.advance.x = wx;
+ UNUSED(sbx);
+ UNUSED(sby);
+ UNUSED(wy);
return -1; /* return an error code to exit the Type 1 parser */
/* immediately. */
}
@@ -1170,39 +1016,40 @@
return -2;
}
-
/* the maxadv_gbuilder_interface is used when computing the maximum */
- /* advance width of all glyphs in a given font. We only process the */
- /* `sbw' operator here, and return an error for all others. */
+ /* advance width of all glyphs in a given font. We only process the */
+ /* 'sbw' operator here, and return an error for all others.. */
- /* Note that `seac' is processed by the T1_Decoder. */
+ /* Note that "seac" is processed by the T1_Decoder */
static
const T1_Builder_Funcs maxadv_builder_interface =
{
- (T1_Builder_EndChar) maxadv_error,
- (T1_Builder_Sbw) maxadv_sbw,
- (T1_Builder_ClosePath)maxadv_error,
- (T1_Builder_RLineTo) maxadv_error,
- (T1_Builder_RMoveTo) maxadv_error,
- (T1_Builder_RCurveTo) maxadv_error
+ (T1_Builder_EndChar) maxadv_error,
+ (T1_Builder_Sbw) maxadv_sbw,
+ (T1_Builder_ClosePath) maxadv_error,
+ (T1_Builder_RLineTo) maxadv_error,
+ (T1_Builder_RMoveTo) maxadv_error,
+ (T1_Builder_RCurveTo) maxadv_error
};
- /* the maxadv_hinter_interface always return an error. */
-
+ /* the maxadv_interface is used when computing the maximum advance */
+ /* with of the set of glyphs in a given font file. We only process */
+ /* the "seac" operator and return immediately.. */
static
const T1_Hinter_Funcs maxadv_hinter_interface =
{
- (T1_Hinter_DotSection) maxadv_error,
- (T1_Hinter_ChangeHints)maxadv_error,
- (T1_Hinter_Stem) maxadv_error,
- (T1_Hinter_Stem3) maxadv_error,
+ (T1_Hinter_DotSection) maxadv_error,
+ (T1_Hinter_ChangeHints) maxadv_error,
+ (T1_Hinter_Stem) maxadv_error,
+ (T1_Hinter_Stem3) maxadv_error,
};
+
LOCAL_FUNC
FT_Error T1_Compute_Max_Advance( T1_Face face,
- FT_Int* max_advance )
+ FT_Int *max_advance )
{
FT_Error error;
T1_Decoder decoder;
@@ -1209,10 +1056,9 @@
FT_Int glyph_index;
T1_Font* type1 = &face->type1;
-
*max_advance = 0;
- /* Initialize load decoder */
+ /* Initialise load decoder */
T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
T1_Init_Builder( &decoder.builder, face, 0, 0,
@@ -1219,8 +1065,7 @@
&maxadv_builder_interface );
/* For each glyph, parse the glyph charstring and extract */
- /* the advance width. */
-
+ /* the advance width.. */
for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
{
/* now get load the unscaled outline */
@@ -1230,49 +1075,49 @@
type1->num_subrs,
type1->subrs,
type1->subrs_len );
- /* ignore error if one occured - skip to next glyph */
+ /* ignore the error if one occured - skip to next glyph */
}
*max_advance = decoder.builder.advance.x;
-
return T1_Err_Ok;
}
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** UNHINTED GLYPH LOADER *********/
- /********** *********/
- /********** The following code is in charge of loading a *********/
- /********** single outline. It completely ignores hinting *********/
- /********** and is used when FT_LOAD_NO_HINTING is set. *********/
- /********** *********/
- /********** The Type 1 hinter is located in `t1hint.c' *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** UNHINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of loading a *********/
+ /********** single outline. It completely ignores hinting *********/
+ /********** and is used when FT_LOAD_NO_HINTING is set. *********/
+ /********** *********/
+ /********** The Type 1 hinter is located in "t1hint.c" *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+
static
FT_Error close_open_path( T1_Builder* builder )
{
FT_Error error;
- FT_Outline* cur = &builder->current;
+ FT_Outline* cur = builder->current;
FT_Int num_points;
FT_Int first_point;
+ /* Some fonts, like Hershey, are made of "open paths" which are */
+ /* now managed directly by FreeType. In this case, it is necessary */
+ /* to close the path by duplicating its points in reverse order, */
+ /* which is precisely the purpose of this function */
- /* Some fonts, like Hershey, are made of `open paths' which are */
- /* now managed directly by FreeType. In this case, it is necessary */
- /* to close the path by duplicating its points in reverse order, */
- /* which is precisely the purpose of this function. */
-
- /* first compute the number of points to duplicate. */
- if ( cur->n_contours > 1 )
- first_point = cur->contours[cur->n_contours - 2] + 1;
+ /* first compute the number of points to duplicate.. */
+ if (cur->n_contours > 1)
+ first_point = cur->contours[ cur->n_contours-2 ]+1;
else
first_point = 0;
@@ -1284,16 +1129,14 @@
FT_Vector* point;
char* tags;
-
error = T1_Add_Points( builder, num_points );
- if ( error )
- return error;
+ if (error) return error;
point = cur->points + cur->n_points;
- tags = cur->tags + cur->n_points;
+ tags = cur->tags + cur->n_points;
- source_point = point - 2;
- source_tags = tags - 2;
+ source_point = point - 2;
+ source_tags = tags - 2;
cur->n_points += num_points;
@@ -1301,14 +1144,13 @@
do
{
*point++ = *source_point--;
- *tags++ = *source_tags--;
+ *tags++ = *source_tags--;
num_points--;
}
- while ( num_points > 0 );
+ while (num_points > 0);
}
builder->path_begun = 0;
-
return T1_Err_Ok;
}
@@ -1316,52 +1158,46 @@
static
FT_Error gload_closepath( T1_Builder* builder )
{
- FT_Outline* cur = &builder->current;
+ FT_Outline* cur = builder->current;
-
/* save current contour, if any */
if ( cur->n_contours > 0 )
- cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+ cur->contours[cur->n_contours-1] = cur->n_points-1;
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
-
/* hint latest points if needed - this is not strictly required */
/* there, but it helps for debugging, and doesn't affect performance */
if ( builder->pass == 1 )
T1_Hint_Points( builder );
+#endif
-#endif /* T1_CONFIG_OPTION_DISABLE_HINTER */
-
builder->path_begun = 0;
-
return T1_Err_Ok;
}
+
static
FT_Error gload_endchar( T1_Builder* builder )
{
- FT_Outline* cur = &builder->current;
FT_Error error;
-
/* close path if needed */
- if ( builder->path_begun )
+ if (builder->path_begun)
{
error = close_open_path( builder );
- if ( error )
- return error;
+ if (error) return error;
}
error = gload_closepath( builder );
- builder->base.n_points += cur->n_points;
- builder->base.n_contours += cur->n_contours;
+ FT_GlyphLoader_Add( builder->loader );
return error;
}
+
static
FT_Error gload_sbw( T1_Builder* builder,
FT_Pos sbx,
@@ -1376,11 +1212,12 @@
builder->last.x = sbx;
builder->last.y = sby;
-
return 0;
}
+
+
static
FT_Error gload_rlineto( T1_Builder* builder,
FT_Pos dx,
@@ -1387,14 +1224,12 @@
FT_Pos dy )
{
FT_Error error;
- FT_Outline* cur = &builder->current;
+ FT_Outline* cur = builder->current;
FT_Vector vec;
-
/* grow buffer if necessary */
- error = T1_Add_Points( builder, 1 );
- if ( error )
- return error;
+ error = T1_Add_Points ( builder, 1 );
+ if (error) return error;
if ( builder->load_points )
{
@@ -1403,14 +1238,13 @@
vec.y = builder->last.y + dy;
cur->points[cur->n_points] = vec;
- cur->tags [cur->n_points] = FT_Curve_Tag_On;
+ cur->tags [cur->n_points] = FT_Curve_Tag_On;
builder->last = vec;
}
cur->n_points++;
- builder->path_begun = 1;
-
+ builder->path_begun = 1;
return T1_Err_Ok;
}
@@ -1421,23 +1255,20 @@
FT_Pos dy )
{
FT_Error error;
- FT_Outline* cur = &builder->current;
+ FT_Outline* cur = builder->current;
FT_Vector vec;
-
- /* in the case where `path_begun' is set, we have an `rmoveto' */
- /* after some normal path definition. If the face's paint type */
- /* is set to 1, this means that we have an `open path', also */
- /* called a `stroke'. The FreeType raster doesn't support */
- /* opened paths, so we'll close it explicitely there. */
-
+ /* in the case where "path_begun" is set, we have a rmoveto */
+ /* after some normal path definition. When the face's paint */
+ /* type is set to 1, this means that we have an "open path", */
+ /* also called a 'stroke'. The FreeType raster doesn't support */
+ /* opened path, so we'll close it explicitely there.. */
if ( builder->path_begun && builder->face->type1.paint_type == 1 )
{
if ( builder->face->type1.paint_type == 1 )
{
error = close_open_path( builder );
- if ( error )
- return error;
+ if (error) return error;
}
}
@@ -1444,12 +1275,11 @@
/* grow buffer if necessary */
error = T1_Add_Contours( builder, 1 ) ||
T1_Add_Points ( builder, 1 );
- if ( error )
- return error;
+ if (error) return error;
/* save current contour, if any */
if ( cur->n_contours > 0 )
- cur->contours[cur->n_contours - 1] = cur->n_points - 1;
+ cur->contours[cur->n_contours-1] = cur->n_points-1;
if ( builder->load_points )
{
@@ -1457,7 +1287,7 @@
vec.x = builder->last.x + dx;
vec.y = builder->last.y + dy;
cur->points[cur->n_points] = vec;
- cur->tags [cur->n_points] = FT_Curve_Tag_On;
+ cur->tags [cur->n_points] = FT_Curve_Tag_On;
builder->last = vec;
}
@@ -1479,36 +1309,32 @@
FT_Pos dy3 )
{
FT_Error error;
- FT_Outline* cur = &builder->current;
+ FT_Outline* cur = builder->current;
FT_Vector vec;
FT_Vector* points;
char* tags;
/* grow buffer if necessary */
- error = T1_Add_Points( builder, 3 );
- if ( error )
- return error;
+ error = T1_Add_Points ( builder, 3 );
+ if (error) return error;
if ( builder->load_points )
{
/* save point */
points = cur->points + cur->n_points;
- tags = cur->tags + cur->n_points;
+ tags = cur->tags + cur->n_points;
vec.x = builder->last.x + dx1;
vec.y = builder->last.y + dy1;
- points[0] = vec;
- tags[0] = FT_Curve_Tag_Cubic;
+ points[0] = vec; tags[0] = FT_Curve_Tag_Cubic;
vec.x += dx2;
vec.y += dy2;
- points[1] = vec;
- tags[1] = FT_Curve_Tag_Cubic;
+ points[1] = vec; tags[1] = FT_Curve_Tag_Cubic;
vec.x += dx3;
vec.y += dy3;
- points[2] = vec;
- tags[2] = FT_Curve_Tag_On;
+ points[2] = vec; tags[2] = FT_Curve_Tag_On;
builder->last = vec;
}
@@ -1519,6 +1345,8 @@
}
+
+
static
FT_Error gload_ignore( void )
{
@@ -1541,12 +1369,12 @@
static
const T1_Builder_Funcs gload_builder_interface_null =
{
- (T1_Builder_EndChar) gload_ignore,
- (T1_Builder_Sbw) gload_sbw, /* record left bearing */
- (T1_Builder_ClosePath)gload_ignore,
- (T1_Builder_RLineTo) gload_ignore,
- (T1_Builder_RMoveTo) gload_ignore,
- (T1_Builder_RCurveTo) gload_ignore
+ (T1_Builder_EndChar) gload_ignore,
+ (T1_Builder_Sbw) gload_sbw, /* record left bearing */
+ (T1_Builder_ClosePath) gload_ignore,
+ (T1_Builder_RLineTo) gload_ignore,
+ (T1_Builder_RMoveTo) gload_ignore,
+ (T1_Builder_RCurveTo) gload_ignore
};
@@ -1553,18 +1381,19 @@
static
const T1_Hinter_Funcs gload_hinter_interface =
{
- (T1_Hinter_DotSection) gload_ignore, /* dotsection */
- (T1_Hinter_ChangeHints)gload_ignore, /* changehints */
- (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */
- (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */
+ (T1_Hinter_DotSection) gload_ignore, /* dotsection */
+ (T1_Hinter_ChangeHints) gload_ignore, /* changehints */
+ (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */
+ (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */
};
+
/*****************************************************************/
/* */
/* Hinter overview : */
/* */
- /* This is a two-pass hinter. On the first pass, the hints */
+ /* This is a two-pass hinter. On the first pass, the hints */
/* are all recorded by the hinter, and no point is loaded */
/* in the outline. */
/* */
@@ -1582,15 +1411,19 @@
FT_UInt glyph_index,
FT_Bool recurse )
{
- T1_Builder* builder = &decoder->builder;
- T1_GlyphSlot glyph = builder->glyph;
- T1_Font* type1 = &builder->face->type1;
- FT_Outline old_base;
- FT_Error error;
+ T1_Builder* builder = &decoder->builder;
+ T1_GlyphSlot glyph = builder->glyph;
+ T1_Font* type1 = &builder->face->type1;
+ FT_UInt old_points, old_contours;
+ FT_GlyphLoader* loader = decoder->builder.loader;
+ FT_Error error;
-
/* Pass 1 - try to load first glyph, simply recording points */
- old_base = builder->base;
+ old_points = loader->base.outline.n_points;
+ old_contours = loader->base.outline.n_contours;
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader );
+
T1_Reset_Builder( builder, 0 );
builder->no_recurse = recurse;
@@ -1604,61 +1437,51 @@
type1->num_subrs,
type1->subrs,
type1->subrs_len );
- if ( error )
- goto Exit;
+ if (error) goto Exit;
- /* check for composite (i.e. `seac' operator) */
+ /* check for composite (i.e. "seac" operator) */
if ( glyph->root.format == ft_glyph_format_composite )
{
/* this is a composite glyph, we must then load the first one, */
/* then load the second one on top of it and translate it by a */
- /* fixed amount. */
+ /* fixed amount.. */
+ FT_UInt n_base_points;
+ FT_SubGlyph* subglyph = loader->base.subglyphs;
+ T1_Size size = builder->size;
+ FT_Pos dx, dy;
+ FT_Vector left_bearing, advance;
- FT_Outline* cur = &builder->current;
- FT_UInt n_base_points;
- FT_SubGlyph* subglyph = glyph->root.subglyphs;
- T1_Size size = builder->size;
- FT_Pos dx, dy;
- FT_Vector left_bearing, advance;
-
-
/* clean glyph format */
glyph->root.format = ft_glyph_format_none;
- /* First load `bchar' in builder */
+ /* First load "bchar" in builder */
builder->no_recurse = 0;
error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
- if ( error )
- goto Exit;
+ if (error) goto Exit;
/* save the left bearing and width of the base character */
- /* as they will be erased by the next load. */
+ /* as they will be erased by the next load.. */
left_bearing = builder->left_bearing;
advance = builder->advance;
- /* Then load `achar' in builder */
- n_base_points = builder->base.n_points;
+ /* Then load "achar" in builder */
+ n_base_points = builder->base->n_points;
subglyph++;
-
error = t1_load_hinted_glyph( decoder, subglyph->index, 0 );
- if ( error )
- goto Exit;
+ if (error) goto Exit;
- /* adjust contours in accented character outline */
- {
- FT_Int n;
-
-
- for ( n = 0; n < cur->n_contours; n++ )
- cur->contours[n] += n_base_points;
- }
-
/* Finally, move the accent */
dx = FT_MulFix( subglyph->arg1, size->root.metrics.x_scale );
dy = FT_MulFix( subglyph->arg2, size->root.metrics.y_scale );
- dx = ( dx + 32 ) & -64;
- dy = ( dy + 32 ) & -64;
- FT_Outline_Translate( cur, dx, dy );
+ dx = (dx+32) & -64;
+ dy = (dy+32) & -64;
+ {
+ FT_Outline dummy;
+
+ dummy.n_points = loader->base.outline.n_points - n_base_points;
+ dummy.points = loader->base.outline.points + n_base_points;
+ FT_Outline_Translate( &dummy, dx, dy );
+ }
/* restore the left side bearing and */
/* advance width of the base character */
@@ -1671,11 +1494,11 @@
T1_Hint_Stems( &decoder->builder );
/* undo the end-char */
- builder->base.n_points -= builder->current.n_points;
- builder->base.n_contours -= builder->current.n_contours;
+ builder->base->n_points = old_points;
+ builder->base->n_contours = old_contours;
/* Pass 2 - record and scale/hint the points */
- T1_Reset_Builder( &decoder->builder, 0 );
+ T1_Reset_Builder( builder, 0 );
builder->pass = 1;
builder->no_recurse = 0;
@@ -1689,17 +1512,16 @@
}
/* save new glyph tables */
- if ( recurse )
+ if (recurse)
T1_Done_Builder( builder );
Exit:
return error;
}
-
-
-#endif /* T1_CONFIG_OPTION_DISABLE_HINTER */
+#endif
+
LOCAL_FUNC
FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
T1_Size size,
@@ -1706,14 +1528,13 @@
FT_Int glyph_index,
FT_Int load_flags )
{
- FT_Error error;
- T1_Decoder decoder;
- T1_Face face = (T1_Face)glyph->root.face;
- FT_Bool hinting;
- T1_Font* type1 = &face->type1;
+ FT_Error error;
+ T1_Decoder decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font* type1 = &face->type1;
-
- if ( load_flags & FT_LOAD_NO_RECURSE )
+ if (load_flags & FT_LOAD_NO_RECURSE)
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
glyph->x_scale = size->root.metrics.x_scale;
@@ -1728,7 +1549,7 @@
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
- hinting = ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0;
+ hinting = (load_flags & (FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)) == 0;
if ( hinting )
{
@@ -1739,9 +1560,8 @@
error = t1_load_hinted_glyph( &decoder, glyph_index, 1 );
}
else
+#endif
-#endif /* T1_CONFIG_OPTION_DISABLE_HINTER */
-
{
T1_Init_Decoder( &decoder, &gload_hinter_interface );
@@ -1748,7 +1568,7 @@
T1_Init_Builder( &decoder.builder, face, size, glyph,
&gload_builder_interface );
- decoder.builder.no_recurse = ( load_flags & FT_LOAD_NO_RECURSE ) != 0;
+ decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
/* now load the unscaled outline */
error = T1_Parse_CharStrings( &decoder,
@@ -1762,13 +1582,14 @@
T1_Done_Builder( &decoder.builder );
}
- /* Now, set the metrics - this is rather simple, as */
- /* the left side bearing is the xMin, and the top side */
- /* bearing the yMax. */
- if ( !error )
+
+ /* Now, set the metrics.. - this is rather simple, as : */
+ /* the left side bearing is the xMin, and the top side */
+ /* bearing the yMax.. */
+ if (!error)
{
/* for composite glyphs, return only the left side bearing and the */
- /* advance width. */
+ /* advance width.. */
if ( load_flags & FT_LOAD_NO_RECURSE )
{
glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
@@ -1779,20 +1600,18 @@
FT_BBox cbox;
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
-
/* apply the font matrix */
- FT_Outline_Transform( &glyph->root.outline,
- &face->type1.font_matrix );
+ FT_Outline_Transform( &glyph->root.outline, &face->type1.font_matrix );
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
/* grid fit the bounding box if necessary */
- if ( hinting )
+ if (hinting)
{
cbox.xMin &= -64;
cbox.yMin &= -64;
- cbox.xMax = ( cbox.xMax + 63 ) & -64;
- cbox.yMax = ( cbox.yMax + 63 ) & -64;
+ cbox.xMax = ( cbox.xMax+63 ) & -64;
+ cbox.yMax = ( cbox.yMax+63 ) & -64;
}
metrics->width = cbox.xMax - cbox.xMin;
@@ -1802,7 +1621,7 @@
metrics->horiBearingY = cbox.yMax;
/* copy the _unscaled_ advance width */
- metrics->horiAdvance = decoder.builder.advance.x;
+ metrics->horiAdvance = decoder.builder.advance.x;
/* make up vertical metrics */
metrics->vertBearingX = 0;
@@ -1818,29 +1637,28 @@
glyph->root.outline.flags |= ft_outline_reverse_fill;
-#if 0
+ /*
glyph->root.outline.second_pass = TRUE;
- glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+ glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
glyph->root.outline.dropout_mode = 2;
-#endif
+ */
if ( hinting )
{
- /* adjust the advance width */
- /* XXX TODO: consider stem hints grid-fit */
+ /* adjust the advance width */
+ /* XXX : TODO : consider stem hints grid-fit */
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
glyph->x_scale );
}
- else if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
{
/* scale the outline and the metrics */
FT_Int n;
- FT_Outline* cur = &decoder.builder.base;
+ FT_Outline* cur = decoder.builder.base;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
-
/* First of all, scale the points */
for ( n = cur->n_points; n > 0; n--, vec++ )
{
@@ -1859,6 +1677,7 @@
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
+
}
}
}
@@ -1866,5 +1685,3 @@
return error;
}
-
-/* END */
--- a/src/type1/t1gload.h
+++ b/src/type1/t1gload.h
@@ -1,21 +1,37 @@
-/***************************************************************************/
-/* */
-/* t1gload.h */
-/* */
-/* Type 1 Glyph Loader (specification). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/*******************************************************************
+ *
+ * t1gload.h 1.0
+ *
+ * Type1 Glyph Loader.
+ *
+ * Copyright 1996-1998 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ *
+ * The Type 1 glyph loader uses three distinct objects to build
+ * scaled and hinted outlines from a charstrings program. These are :
+ *
+ * - a glyph builder, T1_Builder, used to store the built outline
+ *
+ * - a glyph hinter, T1_Hinter, used to record and apply the stem
+ * hints
+ *
+ * - a charstrings interpreter, T1_Decoder, used to parse the
+ * Type 1 charstrings stream, manage a stack and call the builder
+ * and/or hinter depending on the opcodes.
+ *
+ * Ideally, a Type 2 glyph loader would only need to have its own
+ * T2_Decoder object (assuming the hinter is able to manage all
+ * kinds of hints).
+ *
+ ******************************************************************/
-
#ifndef T1GLOAD_H
#define T1GLOAD_H
@@ -26,15 +42,25 @@
#endif
+/*************************************************************************/
+/* */
+/* <Structure> T1_Builder_Funcs */
+/* */
+/* <Description> */
+/* a structure used to store the address of various functions */
+/* used by a glyph builder to implement the outline's "path */
+/* construction". */
+/* */
+/* */
typedef struct T1_Builder_ T1_Builder;
typedef FT_Error (*T1_Builder_EndChar)( T1_Builder* loader );
- typedef FT_Error (*T1_Builder_Sbw)( T1_Builder* loader,
- FT_Pos sbx,
- FT_Pos sby,
- FT_Pos wx,
- FT_Pos wy );
+ typedef FT_Error (*T1_Builder_Sbw) ( T1_Builder* loader,
+ FT_Pos sbx,
+ FT_Pos sby,
+ FT_Pos wx,
+ FT_Pos wy );
typedef FT_Error (*T1_Builder_ClosePath)( T1_Builder* loader );
@@ -54,17 +80,7 @@
FT_Pos dx3,
FT_Pos dy3 );
-
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* T1_Builder_Funcs */
- /* */
- /* <Description> */
- /* A structure to store the address of various functions used by a */
- /* glyph builder to implement the outline's `path construction'. */
- /* */
- typedef struct T1_Builder_Funcs_
+ typedef struct T1_Builder_Funcs_
{
T1_Builder_EndChar end_char;
T1_Builder_Sbw set_bearing_point;
@@ -76,98 +92,94 @@
} T1_Builder_Funcs;
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* T1_Builder */
- /* */
- /* <Description> */
- /* A structure used during glyph loading to store its outline. */
- /* */
- /* <Fields> */
- /* memory :: The current memory object. */
- /* */
- /* face :: The current face object. */
- /* */
- /* size :: The current size object. */
- /* */
- /* glyph :: The current glyph slot. */
- /* */
- /* current :: The current glyph outline. */
- /* */
- /* base :: The base glyph outline. */
- /* */
- /* max_points :: The maximum number of points in builder outline. */
- /* */
- /* max_contours :: The maximum number of contours in builder outline. */
- /* */
- /* last :: The last point position. */
- /* */
- /* scale_x :: The horizontal scale (FUnits to sub-pixels). */
- /* */
- /* scale_y :: The vertical scale (FUnits to sub-pixels). */
- /* */
- /* pos_x :: The horizontal translation (for composite glyphs). */
- /* */
- /* pos_y :: The vertical translation (for composite glyphs). */
- /* */
- /* left_bearing :: The left side bearing point. */
- /* */
- /* advance :: The horizontal advance vector. */
- /* */
- /* no_recurse :: */
- /* */
- /* bbox :: The glyph's bounding box. */
- /* */
- /* path_begun :: A flag which indicates that a new path has begun. */
- /* */
- /* load_points :: A flag which indicates, if not set, that no points */
- /* are loaded. */
- /* */
- /* pass :: The pass number for multi-pass hinters. */
- /* */
- /* hint_point :: The index of the next point to hint. */
- /* */
- /* funcs :: A table of builder functions used to perform the */
- /* outline's path construction. */
- /* */
- struct T1_Builder_
- {
- FT_Memory memory;
- T1_Face face;
- T1_Size size;
- T1_GlyphSlot glyph;
- FT_Outline current; /* the current glyph outline */
- FT_Outline base; /* the composite glyph outline */
+/*************************************************************************/
+/* */
+/* <Structure> T1_Builder */
+/* */
+/* <Description> */
+/* a structure used during glyph loading to store its outline. */
+/* */
+/* <Fields> */
+/* system :: current system object */
+/* face :: current face object */
+/* size :: current size object */
+/* glyph :: current glyph slot */
+/* */
+/* current :: current glyph outline */
+/* base :: base glyph outline */
+/* */
+/* max_points :: maximum points in builder outline */
+/* max_contours :: maximum contours in builder outline */
+/* */
+/* last :: last point position */
+/* */
+/* scale_x :: horizontal scale ( FUnits to sub-pixels ) */
+/* scale_y :: vertical scale ( FUnits to sub-pixels ) */
+/* pos_x :: horizontal translation (composite glyphs) */
+/* pos_y :: vertical translation (composite glyph) */
+/* */
+/* left_bearing :: left side bearing point */
+/* advance :: horizontal advance vector */
+/* */
+/* path_begun :: flag, indicates that a new path has begun */
+/* load_points :: flag, if not set, no points are loaded */
+/* */
+/* pass :: pass number for multi-pass hinters */
+/* */
+/* funcs :: table of builder functions used to perform */
+/* the outline's path construction */
+/* */
+/* hint_point :: index of next point to hint.. */
+/* */
+/* */
+/* */
+/* */
- FT_Int max_points; /* capacity of base outline in points */
- FT_Int max_contours; /* capacity of base outline in contours */
+ struct T1_Builder_
+ {
+ FT_Memory memory;
+ T1_Face face;
+ T1_Size size;
+ T1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
- FT_Vector last;
+ FT_Outline* current; /* the current glyph outline */
+ FT_Outline* base; /* the composite glyph outline */
- FT_Fixed scale_x;
- FT_Fixed scale_y;
+ FT_Vector last;
- FT_Pos pos_x;
- FT_Pos pos_y;
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
- FT_Vector left_bearing;
- FT_Vector advance;
- FT_Bool no_recurse;
+ FT_Pos pos_x;
+ FT_Pos pos_y;
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
+ FT_Vector left_bearing;
+ FT_Vector advance;
+ FT_Bool no_recurse;
- FT_Int pass;
- FT_Int hint_point;
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Int pass;
+ FT_Int hint_point;
+
/* path construction function interface */
T1_Builder_Funcs funcs;
};
+/*************************************************************************/
+/* */
+/* <Structure> T1_Hinter_Funcs */
+/* */
+/* <Description> */
+/* a structure used to store the address of various functions */
+/* used by a Type 1 hinter to perform outline hinting. */
+/* */
+
typedef FT_Error (*T1_Hinter_ChangeHints)( T1_Builder* builder );
typedef FT_Error (*T1_Hinter_DotSection)( T1_Builder* builder );
@@ -177,6 +189,7 @@
FT_Pos width,
FT_Bool vertical );
+
typedef FT_Error (*T1_Hinter_Stem3)( T1_Builder* builder,
FT_Pos pos0,
FT_Pos width0,
@@ -186,27 +199,18 @@
FT_Pos width2,
FT_Bool vertical );
-
- /*************************************************************************/
- /* */
- /* <Structure> */
- /* T1_Hinter_Funcs */
- /* */
- /* <Description> */
- /* A structure to store the address of various functions used by a */
- /* Type 1 hinter to perform outline hinting. */
- /* */
typedef struct T1_Hinter_Func_
{
- T1_Hinter_ChangeHints change_hints;
- T1_Hinter_DotSection dot_section;
- T1_Hinter_Stem stem;
- T1_Hinter_Stem3 stem3;
+ T1_Hinter_ChangeHints change_hints;
+ T1_Hinter_DotSection dot_section;
+ T1_Hinter_Stem stem;
+ T1_Hinter_Stem3 stem3;
} T1_Hinter_Funcs;
- typedef enum T1_Operator_
+
+ typedef enum T1_Operator_
{
op_none = 0,
op_endchar,
@@ -240,8 +244,10 @@
} T1_Operator;
+
+
/* execution context charstring zone */
- typedef struct T1_Decoder_Zone_
+ typedef struct T1_Decoder_Zone_
{
FT_Byte* base;
FT_Byte* limit;
@@ -250,54 +256,166 @@
} T1_Decoder_Zone;
- typedef struct T1_Decoder_
+ typedef struct T1_Decoder_
{
- T1_Builder builder;
- T1_Hinter_Funcs hinter;
+ T1_Builder builder;
+ T1_Hinter_Funcs hinter;
- FT_Int stack[T1_MAX_CHARSTRINGS_OPERANDS];
- FT_Int* top;
+ FT_Int stack[ T1_MAX_CHARSTRINGS_OPERANDS ];
+ FT_Int* top;
- T1_Decoder_Zone zones[T1_MAX_SUBRS_CALLS + 1];
- T1_Decoder_Zone* zone;
+ T1_Decoder_Zone zones[ T1_MAX_SUBRS_CALLS+1 ];
+ T1_Decoder_Zone* zone;
- FT_Int flex_state;
- FT_Int num_flex_vectors;
- FT_Vector flex_vectors[7];
+ FT_Int flex_state;
+ FT_Int num_flex_vectors;
+ FT_Vector flex_vectors[7];
} T1_Decoder;
+
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Init_Builder
+ *
+ * <Description>
+ * Initialise a given glyph builder.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ * face :: current face object
+ * size :: current size object
+ * glyph :: current glyph object
+ * funcs :: glyph builder functions (or "methods").
+ *
+ * <Note>
+ * This function is exported for now because it is used by the
+ * "t1dump" utility. Later, it will be accessed through a
+ * format-specific extension
+ *
+ *********************************************************************/
+
LOCAL_DEF
- void T1_Init_Builder( T1_Builder* builder,
- T1_Face face,
- T1_Size size,
- T1_GlyphSlot glyph,
- const T1_Builder_Funcs* funcs );
+ void T1_Init_Builder( T1_Builder* builder,
+ T1_Face face,
+ T1_Size size,
+ T1_GlyphSlot glyph,
+ const T1_Builder_Funcs* funcs );
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Done_Builder
+ *
+ * <Description>
+ * Finalise a given glyph builder. Its content can still be
+ * used after the call, but the function saves important information
+ * within the corresponding glyph slot.
+ *
+ * <Input>
+ * builder :: glyph builder to initialise
+ *
+ * <Note>
+ * This function is exported for now because it is used by the
+ * "t1dump" utility. Later, it will be accessed through a
+ * format-specific extension
+ *
+ *********************************************************************/
+
LOCAL_DEF
void T1_Done_Builder( T1_Builder* builder );
+
+/*********************************************************************
+ *
+ * <Function>
+ * T1_Init_Decoder
+ *
+ * <Description>
+ * Initialise a given Type 1 decoder for parsing
+ *
+ * <Input>
+ * decoder :: Type 1 decoder to initialise
+ * funcs :: hinter functions interface
+ *
+ * <Note>
+ * This function is exported for now because it is used by the
+ * "t1dump" utility. Later, it will be accessed through a
+ * format-specific extension
+ *
+ *********************************************************************/
+
LOCAL_DEF
void T1_Init_Decoder( T1_Decoder* decoder,
const T1_Hinter_Funcs* funcs );
+
+
+ /* Compute the maximum advance width of a font through quick parsing */
LOCAL_DEF
FT_Error T1_Compute_Max_Advance( T1_Face face,
- FT_Int* max_advance );
+ FT_Int *max_advance );
+
+ /* This function is exported, because it is used by the T1Dump utility */
LOCAL_DEF
- FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
- FT_Byte* charstring_base,
- FT_Int charstring_len,
- FT_Int num_subrs,
- FT_Byte** subrs_base,
- FT_Int* subrs_len );
+ FT_Error T1_Parse_CharStrings( T1_Decoder* decoder,
+ FT_Byte* charstring_base,
+ FT_Int charstring_len,
+ FT_Int num_subrs,
+ FT_Byte** subrs_base,
+ FT_Int* subrs_len );
+
+
+/*************************************************************************/
+/* */
+/* <Function> T1_Add_Points */
+/* */
+/* <Description> */
+/* Checks that there is enough room in the current load glyph outline */
+/* to accept "num_points" additional outline points. If not, this */
+/* function grows the load outline's arrays accordingly.. */
+/* */
+/* <Input> */
+/* builder :: pointer to glyph builder object */
+/* num_points :: number of points that will be added later */
+/* */
+/* <Return> */
+/* Type1 error code. 0 means success */
+/* */
+/* <Note> */
+/* This function does NOT update the points count in the glyph loader */
+/* This must be done by the caller itself, after this function is */
+/* invoked.. */
+/* */
LOCAL_DEF
FT_Error T1_Add_Points( T1_Builder* builder,
FT_Int num_points );
+/*************************************************************************/
+/* */
+/* <Function> T1_Add_Contours */
+/* */
+/* <Description> */
+/* Checks that there is enough room in the current load glyph outline */
+/* to accept "num_contours" additional contours. If not, this func */
+/* the load outline's arrays accordingly.. */
+/* */
+/* <Input> */
+/* builder :: pointer to glyph builder object */
+/* num_contours :: number of contours that will be added later */
+/* */
+/* <Return> */
+/* Type1 error code. 0 means success */
+/* */
+/* <Note> */
+/* This function does NOT update the contours count in the load glyph */
+/* This must be done by the caller itself, after this function is */
+/* invoked.. */
+/* */
LOCAL_DEF
FT_Error T1_Add_Contours( T1_Builder* builder,
FT_Int num_contours );
@@ -314,8 +432,4 @@
}
#endif
-
#endif /* T1GLOAD_H */
-
-
-/* END */
--- a/src/type1/t1hinter.c
+++ b/src/type1/t1hinter.c
@@ -1,42 +1,31 @@
-/***************************************************************************/
-/* */
-/* t1hinter.c */
-/* */
-/* Type 1 hinter (body). */
-/* */
-/* 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. */
-/* */
-/***************************************************************************/
+/*******************************************************************
+ *
+ * t1hinter.c 1.2
+ *
+ * Type1 hinter.
+ *
+ * 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.
+ *
+ *
+ * The Hinter is in charge of fitting th scaled outline to the
+ * pixel grid in order to considerably improve the quality of
+ * the Type 1 font driver's output..
+ *
+ ******************************************************************/
-
- /*************************************************************************/
- /* */
- /* The Hinter is in charge of fitting th scaled outline to the pixel */
- /* grid in order to considerably improve the quality of the Type 1 font */
- /* driver's output. */
- /* */
- /*************************************************************************/
-
-
#include <freetype/internal/ftdebug.h>
#include <t1objs.h>
#include <t1hinter.h>
- /*************************************************************************/
- /* */
- /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
- /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
- /* messages during execution. */
- /* */
#undef FT_COMPONENT
-#define FT_COMPONENT trace_t1hint
+#define FT_COMPONENT trace_t1hint /* for debugging/tracing */
#undef ONE_PIXEL
@@ -43,14 +32,13 @@
#define ONE_PIXEL 64
#undef ROUND
-#define ROUND( x ) ( ( x + ONE_PIXEL / 2 ) & -ONE_PIXEL )
+#define ROUND(x) (( x + ONE_PIXEL/2 ) & -ONE_PIXEL)
#undef SCALE
-#define SCALE( val ) FT_MulFix( val, scale )
+#define SCALE(val) FT_MulFix( val, scale )
/* various constants used to describe the alignment of a horizontal */
/* stem with regards to the blue zones */
-
#define T1_ALIGN_NONE 0
#define T1_ALIGN_BOTTOM 1
#define T1_ALIGN_TOP 2
@@ -57,92 +45,95 @@
#define T1_ALIGN_BOTH 3
- /* very simple bubble sort (not a lot of elements, mostly */
- /* pre-sorted, no need for quicksort) */
+/************************************************************************
+ *
+ * <Function>
+ * t1_set_blue_zones
+ *
+ * <Description>
+ * Set a size object's blue zones during reset. This will compute
+ * the "snap" zone corresponding to each blue zone.
+ *
+ * <Input>
+ * size :: handle to target size object
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ * <Note>
+ * This functions does the following :
+ *
+ * 1. It extracts the bottom and top blue zones from the
+ * face object.
+ *
+ * 2. Each zone is then grown by BlueFuzz, overlapping
+ * is eliminated by adjusting the zone edges appropriately
+ *
+ * 3. For each zone, we keep its original font units position, its
+ * original scaled position, as well as its grown/adjusted
+ * edges.
+ *
+ ************************************************************************/
- static
- void t1_sort_blues( FT_Int* blues,
- FT_Int count )
- {
- FT_Int i, swap;
- FT_Int* cur;
-
-
- for ( i = 2; i < count; i += 2 )
- {
- cur = blues + i;
- do
+ /* ultra simple bubble sort (not a lot of elements, mostly */
+ /* pre-sorted, no need for quicksort) */
+ static
+ void t1_sort_blues( FT_Int* blues,
+ FT_Int count )
{
- if ( cur[-1] < cur[0] )
- break;
+ FT_Int i, swap;
+ FT_Int* cur;
- swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap;
- swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap;
- cur -= 2;
- } while ( cur > blues );
- }
- }
+ for ( i = 2; i < count; i += 2 )
+ {
+ cur = blues + i;
+ do
+ {
+ if ( cur[-1] < cur[0] )
+ break;
+ swap = cur[-2]; cur[-2] = cur[0]; cur[0] = swap;
+ swap = cur[-1]; cur[-1] = cur[1]; cur[1] = swap;
+ cur -= 2;
+ }
+ while ( cur > blues );
+ }
+ }
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_set_blue_zones */
- /* */
- /* <Description> */
- /* Sets a size object's blue zones during reset. This will compute */
- /* the `snap' zone corresponding to each blue zone. */
- /* */
- /* <InOut> */
- /* size :: A handle to target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This functions does the following: */
- /* */
- /* 1. It extracts the bottom and top blue zones from the face object. */
- /* */
- /* 2. Each zone is then grown by `BlueFuzz', overlapping is */
- /* eliminated by adjusting the zone edges appropriately. */
- /* */
- /* 3. For each zone, we keep its original font units position, its */
- /* original scaled position, as well as its grown/adjusted edges. */
- /* */
+
static
FT_Error t1_set_blue_zones( T1_Size size )
{
- T1_Face face = (T1_Face)size->root.face;
- T1_Private* priv = &face->type1.private_dict;
- FT_Int n;
- FT_Int blues[24];
- FT_Int num_bottom;
- FT_Int num_top;
- FT_Int num_blues;
- T1_Size_Hints* hints = size->hints;
- T1_Snap_Zone* zone;
- FT_Pos pix, orus;
- FT_Pos min, max, threshold;
- FT_Fixed scale;
- FT_Bool is_bottom;
+ T1_Face face = (T1_Face)size->root.face;
+ T1_Private* priv = &face->type1.private_dict;
+ FT_Int n;
+ FT_Int blues[24];
+ FT_Int num_bottom;
+ FT_Int num_top;
+ FT_Int num_blues;
+ T1_Size_Hints* hints = size->hints;
+ T1_Snap_Zone* zone;
+ FT_Pos pix, orus;
+ FT_Pos min, max, threshold;
+ FT_Fixed scale;
+ FT_Bool is_bottom;
+ /**********************************************************************/
+ /* */
+ /* COPY BOTTOM AND TOP BLUE ZONES IN LOCAL ARRAYS */
+ /* */
+ /* */
- /***********************************************************************/
- /* */
- /* copy bottom and top blue zones in local arrays */
- /* */
-
/* First of all, check the sizes of the /BlueValues and /OtherBlues */
- /* tables. They all must contain an even number of arguments. */
+ /* tables. They all must contain an even number of arguments */
if ( priv->num_other_blues & 1 ||
priv->num_blue_values & 1 )
{
- FT_ERROR(( "t1_set_blue_zones: odd number of blue values\n" ));
+ FT_ERROR(( "T1.Copy_Blues : odd number of blue values\n" ));
return T1_Err_Syntax_Error;
}
- /* copy the bottom blue zones from /OtherBlues */
+ /* copy the bottom blue zones from /OtherBlues */
num_top = 0;
num_bottom = priv->num_other_blues;
@@ -149,12 +140,12 @@
for ( n = 0; n < num_bottom; n ++ )
blues[n] = priv->other_blues[n];
- /* add the first blue zone in /BlueValues to the table */
+ /* Add the first blue zone in /BlueValues to the table */
num_top = priv->num_blue_values - 2;
if ( num_top >= 0 )
{
- blues[num_bottom ] = priv->blue_values[0];
- blues[num_bottom + 1] = priv->blue_values[1];
+ blues[ num_bottom ] = priv->blue_values[0];
+ blues[num_bottom+1] = priv->blue_values[1];
num_bottom += 2;
}
@@ -168,7 +159,7 @@
if ( num_top > 0 )
{
for ( n = 0; n < num_top; n++ )
- blues[num_bottom + n] = priv->blue_values[n + 2];
+ blues[ num_bottom+n ] = priv->blue_values[n+2];
/* sort the top blue zones */
t1_sort_blues( blues + num_bottom, num_top );
@@ -179,29 +170,28 @@
num_blues = num_top + num_bottom;
hints->num_blue_zones = ( num_blues ) >> 1;
- /***********************************************************************/
- /* */
- /* build blue snap zones from the local blues arrays */
- /* */
+ /**********************************************************************/
+ /* */
+ /* BUILD BLUE SNAP ZONES FROM THE LOCAL BLUES ARRAYS */
+ /* */
+ /* */
scale = size->root.metrics.y_scale;
zone = hints->blue_zones;
- threshold = ONE_PIXEL / 4; /* 0.25 pixels */
+ threshold = ONE_PIXEL/4; /* 0.25 pixels */
for ( n = 0; n < num_blues; n += 2, zone ++ )
{
- is_bottom = n < num_bottom ? 1 : 0;
+ is_bottom = ( n < num_bottom ? 1 : 0 );
- orus = blues[n + is_bottom]; /* get alignement coordinate */
- pix = SCALE( orus ); /* scale it */
+ orus = blues[n+is_bottom]; /* get alignement coordinate */
+ pix = SCALE( orus ); /* scale it */
- min = SCALE( blues[n ] - priv->blue_fuzz );
- max = SCALE( blues[n + 1] + priv->blue_fuzz );
+ min = SCALE( blues[ n ] - priv->blue_fuzz );
+ max = SCALE( blues[n+1] + priv->blue_fuzz );
- if ( min > pix - threshold )
- min = pix - threshold;
- if ( max < pix + threshold )
- max = pix + threshold;
+ if ( min > pix - threshold ) min = pix - threshold;
+ if ( max < pix + threshold ) max = pix + threshold;
zone->orus = orus;
zone->pix = pix;
@@ -213,22 +203,24 @@
zone = hints->blue_zones;
for ( n = 0; n < num_blues-2; n += 2, zone ++ )
{
- if ( n != num_bottom - 2 &&
+ if ( n != num_bottom-2 &&
zone[0].max > zone[1].min )
- zone[0].max = zone[1].min = ( zone[0].pix + zone[1].pix ) / 2;
+ {
+ zone[0].max = zone[1].min = (zone[0].pix+zone[1].pix)/2;
+ }
}
+
/* Compare the current pixel size with the BlueScale value */
- /* to know whether to supress overshoots. */
+ /* to know wether to supress overshoots.. */
hints->supress_overshoots =
- size->root.metrics.y_ppem < FT_MulFix( 1000, priv->blue_scale );
+ ( size->root.metrics.y_ppem < FT_MulFix(1000,priv->blue_scale) );
+ /* Now print the new blue values in tracing mode */
#ifdef FT_DEBUG_LEVEL_TRACE
- /* Now print the new blue values in tracing mode */
-
- FT_TRACE2(( "Blue Zones for size object at $%08lx:\n", (long)size ));
+ FT_TRACE2(( "Blue Zones for size object at $%08lx :\n", (long)size ));
FT_TRACE2(( " orus pix min max\n" ));
FT_TRACE2(( "-------------------------------\n" ));
@@ -236,14 +228,14 @@
for ( n = 0; n < hints->num_blue_zones; n++ )
{
FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
- zone->orus,
- zone->pix / 64.0,
- zone->min / 64.0,
- zone->max / 64.0 ));
+ zone->orus,
+ zone->pix/64.0,
+ zone->min/64.0,
+ zone->max/64.0 ));
zone++;
}
- FT_TRACE2(( "\nOvershoots are %s\n\n",
- hints->supress_overshoots ? "supressed" : "active" ));
+ FT_TRACE2(( "\nOver shoots are %s\n\n",
+ hints->supress_overshoots ? "supressed" : "active" ));
#endif /* DEBUG_LEVEL_TRACE */
@@ -251,35 +243,38 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_set_snap_zones */
- /* */
- /* <Description> */
- /* This function set a size object's stem snap zones. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* This function performs the following: */
- /* */
- /* 1. It reads and scales the stem snap widths from the parent face. */
- /* */
- /* 2. A `snap zone' is computed for each snap width, by `growing' it */
- /* with a threshold of 1/2 pixel. Overlapping is avoided through */
- /* proper edge adjustment. */
- /* */
- /* 3. Each width whose zone contain the scaled standard set width is */
- /* removed from the table. */
- /* */
- /* 4. Finally, the standard set width is scaled, and its correponding */
- /* `snap zone' is inserted into the sorted snap zones table. */
- /* */
+
+/************************************************************************
+ *
+ * <Function>
+ * t1_set_snap_zones
+ *
+ * <Description>
+ * This function set a size object's stem snap zones.
+ *
+ * <Input>
+ * size :: handle to target size object
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ * <Note>
+ * This function performs the following :
+ *
+ * 1. It reads and scales the stem snap widths from the parent face
+ *
+ * 2. A "snap zone" is computed for each snap width, by "growing"
+ * it with a threshold of a 1/2 pixel. Overlapping is avoided
+ * through proper edge adjustment.
+ *
+ * 3. Each width whose zone contain the scaled standard set width
+ * is removed from the table
+ *
+ * 4. Finally, the standard set width is scaled, and its correponding
+ * "snap zone" is inserted into the sorted snap zones table
+ *
+ ************************************************************************/
+
static
FT_Error t1_set_snap_zones( T1_Size size )
{
@@ -290,11 +285,10 @@
FT_Pos standard_width;
FT_Fixed scale;
- T1_Face face = (T1_Face)size->root.face;
- T1_Private* priv = &face->type1.private_dict;
+ T1_Face face = (T1_Face)size->root.face;
+ T1_Private* priv = &face->type1.private_dict;
T1_Size_Hints* hints = size->hints;
-
/* start with horizontal snap zones */
direction = 0;
standard_width = priv->standard_width[0];
@@ -303,18 +297,16 @@
orgs = priv->snap_widths;
scale = size->root.metrics.x_scale;
- while ( direction < 2 )
+ while (direction < 2)
{
- /*********************************************************************/
- /* */
- /* Read and scale stem snap widths table from the physical font */
- /* record. */
- /* */
-
+ /*****************************************************************/
+ /* */
+ /* Read and scale stem snap widths table from the physical */
+ /* font record. */
+ /* */
FT_Pos prev, orus, pix, min, max, threshold;
-
- threshold = ONE_PIXEL / 4;
+ threshold = ONE_PIXEL/4;
zone = base_zone;
if ( n_zones > 0 )
@@ -321,8 +313,8 @@
{
orus = *orgs++;
pix = SCALE( orus );
- min = pix - threshold;
- max = pix + threshold;
+ min = pix-threshold;
+ max = pix+threshold;
zone->orus = orus;
zone->pix = pix;
@@ -334,12 +326,12 @@
orus = *orgs++;
pix = SCALE( orus );
- if ( pix - prev < 2 * threshold )
+ if ( pix-prev < 2*threshold )
{
- min = max = ( pix + prev ) / 2;
+ min = max = (pix+prev)/2;
}
else
- min = pix - threshold;
+ min = pix-threshold;
zone->max = max;
zone++;
@@ -347,20 +339,19 @@
zone->pix = pix;
zone->min = min;
- max = pix + threshold;
+ max = pix+threshold;
prev = pix;
}
zone->max = max;
}
+ /* print the scaled stem snap values in tracing modes */
#ifdef FT_DEBUG_LEVEL_TRACE
- /* print the scaled stem snap values in tracing mode */
+ FT_TRACE2(( "Set_Snap_Zones : first %s pass\n",
+ direction ? "vertical" : "horizontal" ));
- FT_TRACE2(( "Set_Snap_Zones: first %s pass\n",
- direction ? "vertical" : "horizontal" ));
-
- FT_TRACE2(( "Scaled original stem snap zones:\n" ));
+ FT_TRACE2(( "Scaled original stem snap zones :\n" ));
FT_TRACE2(( " orus pix min max\n" ));
FT_TRACE2(( "-----------------------------\n" ));
@@ -367,32 +358,30 @@
zone = base_zone;
for ( n = 0; n < n_zones; n++, zone++ )
FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
- zone->orus,
- zone->pix / 64.0,
- zone->min / 64.0,
- zone->max / 64.0 ));
- FT_TRACE2(( "\n" ));
+ zone->orus,
+ zone->pix/64.0,
+ zone->min/64.0,
+ zone->max/64.0 ));
+ FT_TRACE2(( "\n" ));
- FT_TRACE2(( "Standard width = %d\n", standard_width ));
+ FT_TRACE2(( "Standard width = %d\n", standard_width ));
+#endif
-#endif /* FT_DEBUG_LEVEL_TRACE */
+ /*****************************************************************/
+ /* */
+ /* Now, each snap width which is in the range of the standard */
+ /* set width will be removed from the list.. */
+ /* */
- /*********************************************************************/
- /* */
- /* Now, each snap width which is in the range of the standard set */
- /* width will be removed from the list. */
- /* */
-
if ( standard_width > 0 )
{
T1_Snap_Zone* parent;
FT_Pos std_pix, std_min, std_max;
-
std_pix = SCALE( standard_width );
- std_min = std_pix - threshold;
- std_max = std_pix + threshold;
+ std_min = std_pix-threshold;
+ std_max = std_pix+threshold;
num_zones = 0;
zone = base_zone;
@@ -403,10 +392,8 @@
if ( zone->pix >= std_min && zone->pix <= std_max )
{
/* this zone must be removed from the list */
- if ( std_min > zone->min )
- std_min = zone->min;
- if ( std_max < zone->max )
- std_max = zone->max;
+ if ( std_min > zone->min ) std_min = zone->min;
+ if ( std_max < zone->max ) std_max = zone->max;
}
else
{
@@ -416,16 +403,14 @@
zone++;
}
- /*******************************************************************/
- /* */
- /* Now, insert the standard width zone */
- /* */
+ /**********************************************/
+ /* Now, insert the standard width zone */
- zone = base_zone + num_zones;
+ zone = base_zone+num_zones;
while ( zone > base_zone && zone[-1].pix > std_max )
{
zone[0] = zone[-1];
- zone--;
+ zone --;
}
/* check border zones */
@@ -432,7 +417,7 @@
if ( zone > base_zone && zone[-1].max > std_min )
zone[-1].max = std_min;
- if ( zone < base_zone + num_zones && zone[1].min < std_max )
+ if ( zone < base_zone+num_zones && zone[1].min < std_max )
zone[1].min = std_max;
zone->orus = standard_width;
@@ -446,19 +431,16 @@
num_zones = n_zones;
/* save total number of stem snaps now */
- if ( direction )
- hints->num_snap_heights = num_zones;
- else
- hints->num_snap_widths = num_zones;
+ if (direction) hints->num_snap_heights = num_zones;
+ else hints->num_snap_widths = num_zones;
+ /* print the scaled stem snap values in tracing modes */
#ifdef FT_DEBUG_LEVEL_TRACE
- /* print the scaled stem snap values in tracing mode */
+ FT_TRACE2(( "Set_Snap_Zones : second %s pass\n",
+ direction ? "vertical" : "horizontal" ));
- FT_TRACE2(( "Set_Snap_Zones: second %s pass\n",
- direction ? "vertical" : "horizontal" ));
-
- FT_TRACE2(( "Scaled clipped stem snap zones:\n" ));
+ FT_TRACE2(( "Scaled clipped stem snap zones :\n" ));
FT_TRACE2(( " orus pix min max\n" ));
FT_TRACE2(( "-----------------------------\n" ));
@@ -465,16 +447,15 @@
zone = base_zone;
for ( n = 0; n < num_zones; n++, zone++ )
FT_TRACE2(( " %3d %.2f %.2f %.2f\n",
- zone->orus,
- zone->pix / 64.0,
- zone->min / 64.0,
- zone->max / 64.0 ));
+ zone->orus,
+ zone->pix/64.0,
+ zone->min/64.0,
+ zone->max/64.0 ));
FT_TRACE2(( "\n" ));
FT_TRACE2(( "Standard width = %d\n", standard_width ));
+#endif
-#endif /* FT_DEBUG_LEVEL_TRACE */
-
/* continue with vertical snap zone */
direction++;
standard_width = priv->standard_height[0];
@@ -488,145 +469,153 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_New_Size_Hinter */
- /* */
- /* <Description> */
- /* Allocates a new hinter structure for a given size object. */
- /* */
- /* <InOut> */
- /* size :: A handle to the target size object. */
- /* */
- /* <Return> */
- /* FreeType Error code. 0 means success. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * T1_New_Size_Hinter
+ *
+ * <Description>
+ * Allocates a new hinter structure for a given size object
+ *
+ * <Input>
+ * size :: handle to target size object
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ ************************************************************************/
+
LOCAL_FUNC
FT_Error T1_New_Size_Hinter( T1_Size size )
{
FT_Memory memory = size->root.face->memory;
-
- return MEM_Alloc( size->hints, sizeof ( *size->hints ) );
+ return MEM_Alloc( size->hints, sizeof(*size->hints) );
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Done_Size_Hinter */
- /* */
- /* <Description> */
- /* Releases a given size object's hinter structure. */
- /* */
- /* <Input> */
- /* size :: A handle to the target size object. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * T1_Done_Size_Hinter
+ *
+ * <Description>
+ * Releases a given size object's hinter structure
+ *
+ * <Input>
+ * size :: handle to target size object
+ *
+ ************************************************************************/
+
LOCAL_FUNC
- void T1_Done_Size_Hinter( T1_Size size )
+ void T1_Done_Size_Hinter( T1_Size size )
{
FT_Memory memory = size->root.face->memory;
-
FREE( size->hints );
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Reset_Size_Hinter */
- /* */
- /* <Description> */
- /* Recomputes hinting information when a given size object has */
- /* changed its resolutions/char sizes/pixel sizes. */
- /* */
- /* <InOut> */
- /* size :: A handle to the size object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+
+/************************************************************************
+ *
+ * <Function>
+ * T1_Reset_Size_Hinter
+ *
+ * <Description>
+ * Recomputes hinting information when a given size object has
+ * changed its resolutions/char sizes/pixel sizes
+ *
+ * <Input>
+ * size :: handle to size object
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ ************************************************************************/
+
LOCAL_FUNC
FT_Error T1_Reset_Size_Hinter( T1_Size size )
{
- return t1_set_blue_zones( size ) || t1_set_snap_zones( size );
+ return t1_set_blue_zones(size) || t1_set_snap_zones(size);
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_New_Glyph_Hinter */
- /* */
- /* <Description> */
- /* Allocates a new hinter structure for a given glyph slot. */
- /* */
- /* <InOut> */
- /* glyph :: A handle to the target glyph slot. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
+
+/************************************************************************
+ *
+ * <Function>
+ * T1_New_Glyph_Hinter
+ *
+ * <Description>
+ * Allocates a new hinter structure for a given glyph slot
+ *
+ * <Input>
+ * glyph :: handle to target glyph slot
+ *
+ * <Return>
+ * Error code. 0 means success
+ *
+ ************************************************************************/
+
LOCAL_FUNC
FT_Error T1_New_Glyph_Hinter( T1_GlyphSlot glyph )
{
FT_Memory memory = glyph->root.face->memory;
-
- return MEM_Alloc( glyph->hints, sizeof ( *glyph->hints ) );
+ return MEM_Alloc( glyph->hints, sizeof(*glyph->hints) );
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Done_Glyph_Hinter */
- /* */
- /* <Description> */
- /* Releases a given glyph slot's hinter structure. */
- /* */
- /* <Input> */
- /* glyph :: A handle to the glyph slot. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * T1_Done_Glyph_Hinter
+ *
+ * <Description>
+ * Releases a given glyph slot's hinter structure
+ *
+ * <Input>
+ * glyph :: handle to glyph slot
+ *
+ ************************************************************************/
+
LOCAL_FUNC
void T1_Done_Glyph_Hinter( T1_GlyphSlot glyph )
{
FT_Memory memory = glyph->root.face->memory;
-
FREE( glyph->hints );
}
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** **********/
- /********** HINTED GLYPH LOADER **********/
- /********** **********/
- /********** The following code is in charge of the first **********/
- /********** and second pass when loading a single outline **********/
- /********** **********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** HINTED GLYPH LOADER *********/
+ /********** *********/
+ /********** The following code is in charge of the first *********/
+ /********** and second pass when loading a single outline *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
static
- FT_Error t1_hinter_ignore( void )
+ FT_Error t1_hinter_ignore( void )
{
- /* do nothing, used for `dotsection' which is unsupported for now */
+ /* do nothing, used for "dotsection" which is unsupported for now */
return 0;
}
-
static
- FT_Error t1_hinter_stem( T1_Builder* builder,
- FT_Pos pos,
- FT_Int width,
- FT_Bool vertical )
+ FT_Error t1_hinter_stem( T1_Builder* builder,
+ FT_Pos pos,
+ FT_Int width,
+ FT_Bool vertical )
{
T1_Stem_Table* stem_table;
T1_Stem_Hint* stems;
@@ -635,7 +624,6 @@
FT_Bool new_stem;
T1_Glyph_Hints* hinter = builder->glyph->hints;
-
/* select the appropriate stem array */
stem_table = vertical ? &hinter->vert_stems : &hinter->hori_stems;
stems = stem_table->stems;
@@ -642,8 +630,9 @@
num_stems = stem_table->num_stems;
/* Compute minimum and maximum coord for the stem */
- min = pos + ( vertical ? builder->left_bearing.x
- : builder->left_bearing.y );
+ min = pos + ( vertical
+ ? builder->left_bearing.x
+ : builder->left_bearing.y );
if ( width >= 0 )
max = min + width;
@@ -656,8 +645,8 @@
max = min;
}
- /* now scan the array. If we find a stem with the same borders */
- /* simply activate it. */
+ /* now scan the array. If we find a stem with the same borders */
+ /* simply activate it.. */
cur_stem = stems;
new_stem = 1;
@@ -667,10 +656,10 @@
cur_stem->max_edge.orus == max )
{
/* This stem is already in the table, simply activate it */
- if ( ( cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE ) == 0 )
+ if ( (cur_stem->hint_flags & T1_HINT_FLAG_ACTIVE) == 0)
{
- cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE;
- stem_table->num_active++;
+ cur_stem->hint_flags |= T1_HINT_FLAG_ACTIVE;
+ stem_table->num_active ++;
}
new_stem = 0;
break;
@@ -678,16 +667,16 @@
}
/* add a new stem to the array when necessary */
- if ( new_stem )
+ if (new_stem)
{
- if ( cur_stem >= stems + T1_HINTER_MAX_EDGES )
+ if (cur_stem >= stems + T1_HINTER_MAX_EDGES)
{
- FT_ERROR(( "t1_hinter_stem: : too many stems in glyph charstring\n" ));
+ FT_ERROR(( "T1.Hinter : too many stems in glyph charstring\n" ));
return T1_Err_Syntax_Error;
}
/* on the first pass, we record the stem, otherwise, this is */
- /* a bug in the glyph loader! */
+ /* a bug in the glyph loader !! */
if ( builder->pass == 0 )
{
cur_stem->min_edge.orus = min;
@@ -699,7 +688,7 @@
}
else
{
- FT_ERROR(( "t1_hinter_stem: fatal glyph loader bug - pass2-stem\n" ));
+ FT_ERROR(( "T1.Hinter : fatal glyph loader bug - pass2-stem\n" ));
return T1_Err_Syntax_Error;
}
}
@@ -709,16 +698,16 @@
static
- FT_Error t1_hinter_stem3( T1_Builder* builder,
- FT_Pos pos0,
- FT_Int width0,
- FT_Pos pos1,
- FT_Int width1,
- FT_Pos pos2,
- FT_Int width2,
- FT_Bool vertical )
+ FT_Error t1_hinter_stem3( T1_Builder* builder,
+ FT_Pos pos0,
+ FT_Int width0,
+ FT_Pos pos1,
+ FT_Int width1,
+ FT_Pos pos2,
+ FT_Int width2,
+ FT_Bool vertical )
{
- /* For now, simply call `stem' 3 times */
+ /* For now, don't be elitist and simply call "stem" 3 times */
return t1_hinter_stem( builder, pos0, width0, vertical ) ||
t1_hinter_stem( builder, pos1, width1, vertical ) ||
t1_hinter_stem( builder, pos2, width2, vertical );
@@ -732,10 +721,9 @@
T1_Stem_Table* stem_table;
T1_Glyph_Hints* hinter = builder->glyph->hints;
-
- /* If we are in the second pass of glyph hinting, we must */
- /* call the function T1_Hint_Points() on the builder in order */
- /* to force the fit the latest points to the pixel grid. */
+ /* if we're in the second pass of glyph hinting, we must */
+ /* call the function T1_Hint_Points on the builder in order */
+ /* to force the fit the latest points to the pixel grid */
if ( builder->pass == 1 )
T1_Hint_Points( builder );
@@ -747,7 +735,6 @@
T1_Stem_Hint* cur = stem_table->stems;
T1_Stem_Hint* limit = cur + stem_table->num_stems;
-
for ( ; cur < limit; cur++ )
cur->hint_flags &= ~T1_HINT_FLAG_ACTIVE;
@@ -762,40 +749,41 @@
LOCAL_FUNC
const T1_Hinter_Funcs t1_hinter_funcs =
{
- (T1_Hinter_ChangeHints)t1_hinter_changehints,
- (T1_Hinter_DotSection) t1_hinter_ignore,
- (T1_Hinter_Stem) t1_hinter_stem,
- (T1_Hinter_Stem3) t1_hinter_stem3
+ (T1_Hinter_ChangeHints) t1_hinter_changehints,
+ (T1_Hinter_DotSection) t1_hinter_ignore,
+ (T1_Hinter_Stem) t1_hinter_stem,
+ (T1_Hinter_Stem3) t1_hinter_stem3
};
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** *********/
- /********** STEM HINTS MANAGEMENT *********/
- /********** *********/
- /********** The following code is in charge of computing *********/
- /********** the placement of each scaled stem hint. *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+ /********** *********/
+ /********** *********/
+ /********** STEM HINTS MANAGEMENT *********/
+ /********** *********/
+ /********** The following code is in charge of computing *********/
+ /********** the placement of each scaled stem hint.. *********/
+ /********** *********/
+ /**********************************************************************/
+ /**********************************************************************/
+ /**********************************************************************/
+/************************************************************************
+ *
+ * <Function>
+ * t1_sort_hints
+ *
+ * <Description>
+ * Sort the list of active stems in increasing order, through
+ * the "sort" indexing table
+ *
+ * <Input>
+ * table :: a stem hints table
+ *
+ ************************************************************************/
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_sort_hints */
- /* */
- /* <Description> */
- /* Sorta the list of active stems in increasing order, through the */
- /* `sort' indexing table. */
- /* */
- /* <InOut> */
- /* table :: A stem hints table. */
- /* */
static
void t1_sort_hints( T1_Stem_Table* table )
{
@@ -805,7 +793,6 @@
T1_Stem_Hint* stems = table->stems;
FT_Int n;
-
/* record active stems in sort table */
for ( n = 0; n < num_stems; n++ )
{
@@ -813,33 +800,32 @@
sort[num_active++] = n;
}
- /* now sort the indices. There are usually very few stems, */
- /* and they are pre-sorted in 90% cases, so we choose a */
- /* simple bubble sort (quicksort would be slower). */
+ /* now sort the indices. There are usually very few stems, */
+ /* and they are pre-sorted in 90% cases, so we choose a */
+ /* simple bubble sort (quicksort would be slower).. */
for ( n = 1; n < num_active; n++ )
{
- FT_Int p = n - 1;
- T1_Stem_Hint* cur = stems + sort[n];
+ FT_Int p = n-1;
+ T1_Stem_Hint* cur = stems + sort[n];
-
do
{
FT_Int swap;
T1_Stem_Hint* prev = stems + sort[p];
-
- /* note that by definition, the active stems cannot overlap */
- /* so we simply compare their `min' to sort them (we could compare */
- /* their max values also; this wouldn't change anything). */
+ /* note that by definition, the active stems cannot overlap */
+ /* so we simply compare their "min" to sort them.. */
+ /* (we could compare their max, this wouldn't change anything) */
if ( prev->min_edge.orus <= cur->min_edge.orus )
break;
/* swap elements */
- swap = sort[p ];
- sort[p ] = sort[p + 1];
- sort[p + 1] = swap;
+ swap = sort[ p ];
+ sort[ p ] = sort[p+1];
+ sort[p+1] = swap;
p--;
- } while ( p >= 0 );
+ }
+ while ( p >= 0 );
}
table->num_active = num_active;
@@ -846,32 +832,32 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_hint_horizontal_stems */
- /* */
- /* <Description> */
- /* Computes the location of each scaled horizontal stem hint. This */
- /* takes care of the blue zones and the horizontal stem snap table. */
- /* */
- /* <Input> */
- /* table :: The horizontal stem hints table. */
- /* */
- /* hints :: The current size's hint structure. */
- /* */
- /* blueShift :: The value of the /BlueShift as taken from the face */
- /* object. */
- /* */
- /* scale :: The 16.16 scale used to convert outline units to */
- /* 26.6 pixels. */
- /* */
- /* <Note> */
- /* For now, all stems are hinted independently from each other. It */
- /* might be necessary, for better performance, to introduce the */
- /* notion of `controlled' hints describing things like counter-stems, */
- /* stem3, as well as overlapping stems control. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * t1_hint_horizontal_stems
+ *
+ * <Description>
+ * Compute the location of each scaled horizontal stem hint.
+ * This takes care of the blue zones and the horizontal stem
+ * snap table
+ *
+ * <Input>
+ * table :: the horizontal stem hints table
+ * hints :: the current size's hint structure
+ * blueShift :: the value of the /BlueShift as taken from the
+ * face object.
+ * scale :: the 16.16 scale used to convert outline
+ * units to 26.6 pixels
+ *
+ * <Note>
+ * For now, all stems are hinted independently from each other.
+ * It might be necessary, for better performance, to introduce
+ * the notion of "controlled" hints describing things like
+ * counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
static
void t1_hint_horizontal_stems( T1_Stem_Table* table,
T1_Size_Hints* hints,
@@ -881,9 +867,8 @@
T1_Stem_Hint* stem = table->stems;
T1_Stem_Hint* limit = stem + table->num_stems;
-
/* first of all, scale the blueShift */
- blueShift = SCALE( blueShift );
+ blueShift = SCALE(blueShift);
/* then scan the horizontal stem table */
for ( ; stem < limit; stem++ )
@@ -899,28 +884,20 @@
FT_Pos top = top_pix;
FT_Int align = T1_ALIGN_NONE;
-
- /*********************************************************************/
- /* */
- /* Snap pixel width if in stem snap range */
- /* */
-
+ /******************************************************************/
+ /* Snap pixel width if in stem snap range */
{
T1_Snap_Zone* zone = hints->snap_heights;
T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights;
- FT_Pos best_dist = 32000;
- T1_Snap_Zone* best_zone = 0;
+ FT_Pos best_dist = 32000;
+ T1_Snap_Zone* best_zone = 0;
-
for ( ; zone < zone_limit; zone++ )
{
FT_Pos dist;
-
- dist = width_pix - zone->min;
- if ( dist < 0 )
- dist = -dist;
- if ( dist < best_dist )
+ dist = width_pix - zone->min; if (dist < 0) dist = -dist;
+ if (dist < best_dist)
{
best_zone = zone;
best_dist = dist;
@@ -927,43 +904,36 @@
}
}
- if ( best_zone )
+ if (best_zone)
{
- if ( width_pix > best_zone->pix )
+ if (width_pix > best_zone->pix)
{
width_pix -= 0x20;
- if ( width_pix < best_zone->pix )
+ if (width_pix < best_zone->pix)
width_pix = best_zone->pix;
}
else
{
width_pix += 0x20;
- if ( width_pix > best_zone->pix )
+ if (width_pix > best_zone->pix)
width_pix = best_zone->pix;
}
}
}
- /*********************************************************************/
- /* */
- /* round width - minimum 1 pixel if this isn't a ghost stem */
- /* */
-
+ /******************************************************************/
+ /* round width - minimum 1 pixel if this isn't a ghost stem */
if ( width_pix > 0 )
- width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND( width_pix );
+ width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL : ROUND(width_pix) );
- /*********************************************************************/
- /* */
- /* Now check for bottom blue zones alignement */
- /* */
-
+ /******************************************************************/
+ /* Now check for bottom blue zones alignement */
{
FT_Int num_blues = hints->num_bottom_zones;
T1_Snap_Zone* blue = hints->blue_zones;
T1_Snap_Zone* blue_limit = blue + num_blues;
-
for ( ; blue < blue_limit; blue++ )
{
if ( bottom_pix < blue->min )
@@ -974,13 +944,12 @@
align = T1_ALIGN_BOTTOM;
bottom = ROUND( blue->pix );
- /* implement blue shift */
- if ( !hints->supress_overshoots )
+ /* implements blue shift */
+ if (!hints->supress_overshoots)
{
FT_Pos delta = blue->pix - bottom_pix;
-
- delta = delta < blueShift ? 0 : ROUND( delta );
+ delta = ( delta < blueShift ? 0 : ROUND( delta ) );
bottom -= delta;
}
}
@@ -987,11 +956,9 @@
}
}
- /*********************************************************************/
- /* */
- /* check for top blue zones alignement */
- /* */
+ /******************************************************************/
+ /* Check for top blue zones alignement */
{
FT_Int num_blues = hints->num_blue_zones -
hints->num_bottom_zones;
@@ -1001,7 +968,6 @@
T1_Snap_Zone* blue_limit = blue + num_blues;
-
for ( ; blue < blue_limit; blue++ )
{
if ( top_pix < blue->min )
@@ -1009,16 +975,15 @@
if ( top_pix <= blue->max )
{
- align |= T1_ALIGN_TOP;
- top = ROUND( blue->pix );
+ align |= T1_ALIGN_TOP;
+ top = ROUND( blue->pix );
- /* implement blue shift */
- if ( !hints->supress_overshoots )
+ /* implements blue shift */
+ if (!hints->supress_overshoots)
{
FT_Pos delta = top - blue->pix;
-
- delta = delta < blueShift ? 0 : ROUND( delta );
+ delta = ( delta < blueShift ? 0 : ROUND( delta ) );
top += delta;
}
}
@@ -1025,34 +990,34 @@
}
}
- /*********************************************************************/
- /* */
- /* compute the hinted stem position, according to its alignment */
- /* */
- switch ( align )
+ /******************************************************************/
+ /* compute the hinted stem position, according to its alignment */
+ switch (align)
{
- case T1_ALIGN_BOTTOM: /* bottom zone alignment */
- bottom_pix = bottom;
- top_pix = bottom + width_pix;
- break;
+ case T1_ALIGN_BOTTOM: /* bottom zone alignement */
+ bottom_pix = bottom;
+ top_pix = bottom + width_pix;
+ break;
- case T1_ALIGN_TOP: /* top zone alignment */
- top_pix = top;
- bottom_pix = top - width_pix;
- break;
+ case T1_ALIGN_TOP: /* top zone alignement */
+ top_pix = top;
+ bottom_pix = top - width_pix;
- case T1_ALIGN_BOTH: /* bottom+top zone alignment */
- bottom_pix = bottom;
- top_pix = top;
- break;
+ break;
- default: /* no alignment */
- /* XXXX : TODO : Add management of controlled stems */
- bottom = ( SCALE( bottom_orus + top_orus ) - width_pix ) / 2;
+ case T1_ALIGN_BOTH: /* bottom+top zone alignement */
+ bottom_pix = bottom;
+ top_pix = top;
+ break;
- bottom_pix = ROUND( bottom );
- top_pix = bottom_pix + width_pix;
+ default: /* no alignement */
+
+ /* XXXX : TODO : Add management of controlled stems */
+ bottom = ( SCALE(bottom_orus+top_orus) - width_pix )/2;
+
+ bottom_pix = ROUND(bottom);
+ top_pix = bottom_pix + width_pix;
}
stem->min_edge.pix = bottom_pix;
@@ -1061,27 +1026,33 @@
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_hint_vertical_stems */
- /* */
- /* <Description> */
- /* Computes the location of each scaled vertical stem hint. This */
- /* takes care of the vertical stem snap table. */
- /* */
- /* <Input> */
- /* table :: The vertical stem hints table. */
- /* hints :: The current size's hint structure. */
- /* scale :: The 16.16 scale used to convert outline units to */
- /* 26.6 pixels. */
- /* */
- /* <Note> */
- /* For now, all stems are hinted independently from each other. It */
- /* might be necessary, for better performance, to introduce the */
- /* notion of `controlled' hints describing things like counter-stems, */
- /* stem3 as well as overlapping stems control. */
- /* */
+
+
+/************************************************************************
+ *
+ * <Function>
+ * t1_hint_vertical_stems
+ *
+ * <Description>
+ * Compute the location of each scaled vertical stem hint.
+ * This takes care of the vertical stem snap table
+ *
+ * <Input>
+ * table :: the vertical stem hints table
+ * hints :: the current size's hint structure
+ * scale :: the 16.16 scale used to convert outline
+ * units to 26.6 pixels
+ *
+ * <Note>
+ * For now, all stems are hinted independently from each other.
+ * It might be necessary, for better performance, to introduce
+ * the notion of "controlled" hints describing things like
+ * counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
+ /* compute the location of each scaled vertical stem hint. */
+ /* Take care of blue zones and stem snap table */
static
void t1_hint_vertical_stems( T1_Stem_Table* table,
T1_Size_Hints* hints,
@@ -1090,7 +1061,6 @@
T1_Stem_Hint* stem = table->stems;
T1_Stem_Hint* limit = stem + table->num_stems;
-
for ( ; stem < limit; stem++ )
{
FT_Pos stem_left = stem->min_edge.orus;
@@ -1097,7 +1067,6 @@
FT_Pos stem_right = stem->max_edge.orus;
FT_Pos width_pix, left;
-
width_pix = SCALE( stem_right - stem_left );
/* Snap pixel width if in stem snap range */
@@ -1104,19 +1073,15 @@
{
T1_Snap_Zone* zone = hints->snap_heights;
T1_Snap_Zone* zone_limit = zone + hints->num_snap_heights;
- FT_Pos best_dist = 32000;
- T1_Snap_Zone* best_zone = 0;
+ FT_Pos best_dist = 32000;
+ T1_Snap_Zone* best_zone = 0;
-
for ( ; zone < zone_limit; zone++ )
{
FT_Pos dist;
-
- dist = width_pix - zone->min;
- if ( dist < 0 )
- dist = -dist;
- if ( dist < best_dist )
+ dist = width_pix - zone->min; if (dist < 0) dist = -dist;
+ if (dist < best_dist)
{
best_zone = zone;
best_dist = dist;
@@ -1123,18 +1088,18 @@
}
}
- if ( best_zone )
+ if (best_zone)
{
- if ( width_pix > best_zone->pix )
+ if (width_pix > best_zone->pix)
{
width_pix -= 0x20;
- if ( width_pix < best_zone->pix )
+ if (width_pix < best_zone->pix)
width_pix = best_zone->pix;
}
else
{
width_pix += 0x20;
- if ( width_pix > best_zone->pix )
+ if (width_pix > best_zone->pix)
width_pix = best_zone->pix;
}
}
@@ -1142,44 +1107,49 @@
/* round width - minimum 1 pixel if this isn't a ghost stem */
if ( width_pix > 0 )
- width_pix = width_pix < ONE_PIXEL ? ONE_PIXEL
- : ROUND( width_pix );
+ width_pix = ( width_pix < ONE_PIXEL ? ONE_PIXEL :
+ ROUND( width_pix ) );
- /* now place the snapped and rounded stem */
- /* XXX TODO: implement controlled stems for the overlapping */
- /* cases. */
+ /* now place the snapped and rounded stem */
- left = ( SCALE( stem_left + stem_right ) - width_pix ) / 2;
+ /* XXXX : TODO : implement controlled stems for the overlapping */
+ /* cases.. */
- stem->min_edge.pix = ROUND( left );
+ left = ( SCALE(stem_left+stem_right) - width_pix )/2;
+
+ stem->min_edge.pix = ROUND(left);
stem->max_edge.pix = stem->min_edge.pix + width_pix;
}
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* t1_hint_point */
- /* */
- /* <Description> */
- /* Grid-fit a coordinate with regards to a given stem hints table. */
- /* */
- /* <Input> */
- /* table :: The source stem hints table. */
- /* coord :: The original coordinate, expressed in font units. */
- /* scale :: The 16.16 scale used to convert font units into */
- /* 26.6 pixels. */
- /* */
- /* <Return> */
- /* The hinted/scaled value in 26.6 pixels. */
- /* */
- /* <Note> */
- /* For now, all stems are hinted independently from each other. It */
- /* might be necessary, for better performance, to introduce the */
- /* notion of `controlled' hints describing things like counter-stems, */
- /* stem3 as well as overlapping stems control. */
- /* */
+
+
+/************************************************************************
+ *
+ * <Function>
+ * t1_hint_point
+ *
+ * <Description>
+ * Grid-fit a coordinate with regards to a given stem hints table
+ *
+ * <Input>
+ * table :: the source stem hints table
+ * coord :: original coordinate, expressed in font units
+ * scale :: the 16.16 scale used to convert font units into
+ * 26.6 pixels
+ *
+ * <Return>
+ * the hinted/scaled value in 26.6 pixels
+ *
+ * <Note>
+ * For now, all stems are hinted independently from each other.
+ * It might be necessary, for better performance, to introduce
+ * the notion of "controlled" hints describing things like
+ * counter-stems, stem3 as well as overlapping stems control.
+ *
+ ************************************************************************/
+
static
FT_Pos t1_hint_point( T1_Stem_Table* table,
FT_Pos coord,
@@ -1193,10 +1163,9 @@
T1_Edge* max;
FT_Pos delta;
-
/* only hint when there is at least one stem defined */
- if ( num_active <= 0 )
- return SCALE( coord );
+ if (num_active <= 0)
+ return SCALE(coord);
/* scan the stem table to determine placement of coordinate */
/* relative to the list of sorted and stems */
@@ -1204,16 +1173,14 @@
{
cur = table->stems + table->sort[n];
- /* is it on the left of the current edge? */
+ /* is it on the left of the current edge ? */
delta = cur->min_edge.orus - coord;
- if ( delta == 0 )
- return cur->min_edge.pix;
+ if ( delta == 0 ) return cur->min_edge.pix;
- if ( delta > 0 )
+ if (delta > 0)
{
/* if this is the left of the first edge, simply shift */
- if ( !prev )
- return cur->min_edge.pix - SCALE( delta );
+ if (!prev) return cur->min_edge.pix - SCALE(delta);
/* otherwise, interpolate between the maximum of the */
/* previous stem, and the minimum of the current one */
@@ -1222,12 +1189,11 @@
goto Interpolate;
}
- /* is it within the current edge? */
+ /* is it within the current edge ? */
delta = cur->max_edge.orus - coord;
- if ( delta == 0 )
- return cur->max_edge.pix;
+ if ( delta == 0 ) return cur->max_edge.pix;
- if ( delta > 0 )
+ if (delta > 0)
{
/* interpolate within the stem */
min = &cur->min_edge;
@@ -1238,40 +1204,43 @@
/* apparently, this coordinate is on the right of the last stem */
delta = coord - cur->max_edge.orus;
- return cur->max_edge.pix + SCALE( delta );
+ return cur->max_edge.pix + SCALE(delta);
Interpolate:
return min->pix +
- FT_MulDiv( coord - min->orus,
- max->pix - min->pix,
- max->orus - min->orus );
+ FT_MulDiv( coord - min->orus,
+ max->pix - min->pix,
+ max->orus - min->orus );
}
+
+
+
+
#if 1
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Hint_Points */
- /* */
- /* <Description> */
- /* this function grid-fits several points in a given Type 1 builder */
- /* at once. */
- /* */
- /* <Input> */
- /* builder :: A handle to target Type 1 builder. */
- /* */
- /* first :: The first point to hint in the builder's current */
- /* outline. */
- /* */
- /* last :: The last point to hint in the builder's current outline. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * T1_Hint_Points
+ *
+ * <Description>
+ * this function grid-fits several points in a given Type 1 builder
+ * at once.
+ *
+ * <Input>
+ * builder :: handle to target Type 1 builder
+ * first :: first point to hint in builder's current outline
+ * last :: last point to hint in builder's current outline
+ *
+ ************************************************************************/
+
LOCAL_FUNC
void T1_Hint_Points( T1_Builder* builder )
{
FT_Int first = builder->hint_point;
- FT_Int last = builder->current.n_points-1;
+ FT_Int last = builder->current->n_points-1;
T1_Size size = builder->size;
FT_Fixed scale_x = size->root.metrics.x_scale;
@@ -1281,10 +1250,9 @@
T1_Stem_Table* hori_stems = &hints->hori_stems;
T1_Stem_Table* vert_stems = &hints->vert_stems;
- FT_Vector* cur = builder->current.points + first;
+ FT_Vector* cur = builder->current->points + first;
FT_Vector* limit = cur + last - first + 1;
-
/* first of all, sort the active stem hints */
t1_sort_hints( hori_stems );
t1_sort_hints( vert_stems );
@@ -1295,23 +1263,25 @@
cur->y = t1_hint_point( hori_stems, cur->y, scale_y );
}
- builder->hint_point = builder->current.n_points;
+ builder->hint_point = builder->current->n_points;
}
- /*************************************************************************/
- /* */
- /* <Function> */
- /* T1_Hint_Stems */
- /* */
- /* <Description> */
- /* This function is used to compute the location of each stem hint */
- /* between the first and second passes of the glyph loader on the */
- /* charstring. */
- /* */
- /* <Input> */
- /* builder :: A handle to the target builder. */
- /* */
+/************************************************************************
+ *
+ * <Function>
+ * T1_Hint_Stems
+ *
+ * <Description>
+ * This function is used to compute the location of each stem hint
+ * between the first and second passes of the glyph loader on the
+ * charstring.
+ *
+ * <Input>
+ * builder :: handle to target builder
+ *
+ ************************************************************************/
+
LOCAL_FUNC
void T1_Hint_Stems( T1_Builder* builder )
{
@@ -1322,7 +1292,6 @@
FT_Fixed scale_x = size->root.metrics.x_scale;
FT_Fixed scale_y = size->root.metrics.y_scale;
-
t1_hint_horizontal_stems( &hints->hori_stems,
builder->size->hints,
priv->blue_shift,
@@ -1333,7 +1302,4 @@
scale_x );
}
-#endif /* 1 */
-
-
-/* END */
+#endif
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -259,15 +259,11 @@
psnames = (PSNames_Interface*)face->psnames;
if (!psnames)
{
- /* look-up the PSNames driver */
- FT_Driver psnames_driver;
-
- psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
- if (psnames_driver)
- face->psnames = (PSNames_Interface*)
- (psnames_driver->interface.format_interface);
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY(face), "psnames" );
}
-
+ face->psnames = psnames;
+
/* open the tokenizer, this will also check the font format */
error = New_Tokenizer( stream, &tokenizer );
if (error) goto Fail;
@@ -458,16 +454,11 @@
LOCAL_FUNC
void T1_Done_GlyphSlot( T1_GlyphSlot glyph )
{
- FT_Memory memory = glyph->root.face->memory;
- FT_Library library = glyph->root.face->driver->library;
-
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
T1_Done_Glyph_Hinter( glyph );
+#else
+ UNUSED(glyph)
#endif
- /* the bitmaps are created on demand */
- FREE( glyph->root.bitmap.buffer );
- FT_Outline_Done( library, &glyph->root.outline );
- return;
}
@@ -487,66 +478,15 @@
LOCAL_FUNC
FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph )
{
- FT_Library library = glyph->root.face->driver->library;
- FT_Error error;
+ FT_Error error = FT_Err_Ok;
- glyph->max_points = 0;
- glyph->max_contours = 0;
- glyph->root.bitmap.buffer = 0;
-
- error = FT_Outline_New( library, 0, 0, &glyph->root.outline );
- if (error) return error;
-
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
error = T1_New_Glyph_Hinter( glyph );
- if (error)
- FT_Outline_Done( library, &glyph->root.outline );
+#else
+ UNUSED(glyph);
#endif
return error;
- }
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_Driver
- *
- * <Description>
- * Initialise a given Type 1 driver object
- *
- * <Input>
- * driver :: handle to target driver object
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Init_Driver( T1_Driver driver )
- {
- UNUSED(driver);
- return T1_Err_Ok;
- }
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Driver
- *
- * <Description>
- * finalise a given Type 1 driver
- *
- * <Input>
- * driver :: handle to target Type 1 driver
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Driver( T1_Driver driver )
- {
- UNUSED(driver);
}
--- a/src/type1/t1objs.h
+++ b/src/type1/t1objs.h
@@ -260,40 +260,6 @@
-/*******************************************************************
- *
- * <Function> T1_Init_Driver
- *
- * <Description>
- * Initialise a given Type 1 driver object
- *
- * <Input>
- * driver :: handle to target driver object
- *
- * <Return>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_Driver( T1_Driver driver );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Driver
- *
- * <Description>
- * finalise a given Type 1 driver
- *
- * <Input>
- * driver :: handle to target Type 1 driver
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Driver( T1_Driver driver );
#ifdef __cplusplus
}
--- a/src/type1z/module.mk
+++ b/src/type1z/module.mk
@@ -1,7 +1,7 @@
make_module_list: add_type1z_driver
add_type1z_driver:
- $(OPEN_DRIVER)t1z_driver_interface$(CLOSE_DRIVER)
+ $(OPEN_DRIVER)t1z_driver_class$(CLOSE_DRIVER)
$(ECHO_DRIVER)type1z $(ECHO_DRIVER_DESC)Postscript font files with extension *.pfa or *.pfb$(ECHO_DRIVER_DONE)
# EOF
--- a/src/type1z/t1driver.c
+++ b/src/type1z/t1driver.c
@@ -55,26 +55,21 @@
/* time). */
/* */
static
- FTDriver_Interface Get_Interface( FT_Driver driver,
- const FT_String* interface )
+ FT_Module_Interface Get_Interface( FT_Driver driver,
+ const FT_String* interface )
{
UNUSED(driver);
UNUSED(interface);
-#ifndef T1_CONFIG_OPTION_NO_AFM
- if ( strcmp( (const char*)interface, "attach_file" ) == 0 )
- return (FTDriver_Interface)T1_Read_AFM;
-#endif
-
#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
- return (FTDriver_Interface)T1_Get_Multi_Master;
+ return (FT_Module_Interface)T1_Get_Multi_Master;
if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
- return (FTDriver_Interface)T1_Set_MM_Design;
+ return (FT_Module_Interface)T1_Set_MM_Design;
if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
- return (FTDriver_Interface)T1_Set_MM_Blend;
+ return (FT_Module_Interface)T1_Set_MM_Blend;
#endif
return 0;
}
@@ -132,76 +127,6 @@
}
#endif
- /******************************************************************/
- /* */
- /* <Function> Set_Char_Sizes */
- /* */
- /* <Description> */
- /* A driver method used to reset a size's character sizes */
- /* (horizontal and vertical) expressed in fractional points. */
- /* */
- /* <Input> */
- /* size :: handle to target size object */
- /* char_width :: character width expressed in 26.6 points */
- /* char_height :: character height expressed in 26.6 points */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success */
- /* */
- static
- FT_Error Set_Char_Sizes( T1_Size size,
- FT_F26Dot6 char_width,
- FT_F26Dot6 char_height,
- FT_UInt horz_resolution,
- FT_UInt vert_resolution )
- {
- UNUSED(char_width);
- UNUSED(char_height);
- UNUSED(horz_resolution);
- UNUSED(vert_resolution);
-
- size->valid = FALSE;
- return T1_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> */
- /* size :: handle to target size object */
- /* */
- /* pixel_width :: character width expressed in 26.6 points */
- /* */
- /* pixel_height :: character height expressed in 26.6 points */
- /* */
- /* char_size :: the corresponding character size in points */
- /* This value is only sent to the TrueType */
- /* bytecode interpreter, even though 99% of */
- /* glyph programs will simply ignore it. A */
- /* safe value there is the maximum of the */
- /* pixel width and height (multiplied by */
- /* 64 to make it a 26.6 fixed float !) */
- /* <Return> */
- /* FreeType error code. 0 means success */
- /* */
- static
- FT_Error Set_Pixel_Sizes( T1_Size size,
- FT_Int pixel_width,
- FT_Int pixel_height )
- {
- UNUSED(pixel_width);
- UNUSED(pixel_height);
-
- size->valid = FALSE;
- return T1_Reset_Size(size);
- }
-
/*************************************************************************/
/* */
/* <Function> */
@@ -298,117 +223,48 @@
}
- /******************************************************************/
- /* */
- /* <Struct> FT_DriverInterface */
- /* */
- /* <Description> */
- /* A structure used to hold a font driver's basic interface */
- /* used by the high-level parts of FreeType (or other apps) */
- /* */
- /* Most scalable drivers provide a specialized interface to */
- /* access format-specific features. It can be retrieved with */
- /* a call to the "get_format_interface", and should be defined */
- /* in each font driver header (e.g. ttdriver.h, t1driver.h,..) */
- /* */
- /* All fields are function pointers .. */
- /* */
- /* */
- /* <Fields> */
- /* */
- /* new_engine :: */
- /* used to create and initialise a new driver object */
- /* */
- /* done_engine :: */
- /* used to finalise and destroy a given driver object */
- /* */
- /* get_format_interface :: */
- /* return a typeless pointer to the format-specific */
- /* driver interface. */
- /* */
- /* new_face :: */
- /* create a new face object from a resource */
- /* */
- /* done_face :: */
- /* discards a face object, as well as all child objects */
- /* ( sizes, charmaps, glyph slots ) */
- /* */
- /* get_face_properties :: */
- /* return generic face properties */
- /* */
- /* get_kerning :: */
- /* return the kerning vector corresponding to a pair */
- /* of glyphs, expressed in unscaled font units. */
- /* */
- /* new_size :: */
- /* create and initialise a new scalable size object. */
- /* */
- /* new_fixed_size :: */
- /* create and initialise a new fixed-size object. */
- /* */
- /* done_size :: */
- /* finalize a given face size object. */
- /* */
- /* set_size_resolutions :: */
- /* reset a scalable size object's output resolutions */
- /* */
- /* set_size_char_sizes :: */
- /* reset a scalable size object's character size */
- /* */
- /* set_pixel_sizes :: */
- /* reset a face size object's pixel dimensions. Applies */
- /* to both scalable and fixed faces. */
- /* */
- /* new_glyph_slot :: */
- /* create and initialise a new glyph slot */
- /* */
- /* done_glyph_slot :: */
- /* discard a given glyph slot */
- /* */
- /* load_glyph :: */
- /* load a given glyph into a given slot */
- /* */
- /* get_glyph_metrics :: */
- /* return a loaded glyph's metrics. */
- /* */
-
- const FT_DriverInterface t1z_driver_interface =
+ const FT_Driver_Class t1z_driver_class =
{
- sizeof( FT_DriverRec ),
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1",
+ 100,
+ 200,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor) T1_Init_Driver,
+ (FT_Module_Destructor) T1_Done_Driver,
+ (FT_Module_Requester) Get_Interface,
+ },
+
sizeof( T1_FaceRec ),
sizeof( T1_SizeRec ),
sizeof( T1_GlyphSlotRec ),
- "type1",
- 100,
- 200,
-
- 0, /* format interface */
-
- (FTDriver_initDriver) T1_Init_Driver,
- (FTDriver_doneDriver) T1_Done_Driver,
-
- (FTDriver_getInterface) Get_Interface,
-
(FTDriver_initFace) T1_Init_Face,
(FTDriver_doneFace) T1_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot) 0,
+ (FTDriver_doneGlyphSlot) 0,
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes) 0,
+ (FTDriver_loadGlyph) T1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
#ifdef T1_CONFIG_OPTION_NO_AFM
(FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
#else
(FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) T1_Read_AFM,
#endif
+ (FTDriver_getAdvances) 0
- (FTDriver_initSize) T1_Init_Size,
- (FTDriver_doneSize) T1_Done_Size,
- (FTDriver_setCharSizes) Set_Char_Sizes,
- (FTDriver_setPixelSizes) Set_Pixel_Sizes,
-
- (FTDriver_initGlyphSlot) T1_Init_GlyphSlot,
- (FTDriver_doneGlyphSlot) T1_Done_GlyphSlot,
- (FTDriver_loadGlyph) T1_Load_Glyph,
-
- (FTDriver_getCharIndex) Get_Char_Index,
};
@@ -434,9 +290,9 @@
#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
- EXPORT_FUNC(FT_DriverInterface*) getDriverInterface( void )
+ EXPORT_FUNC(const FT_Driver_Class*) getDriverClass( void )
{
- return &t1z_driver_interface;
+ return &t1z_driver_class;
}
#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
--- a/src/type1z/t1driver.h
+++ b/src/type1z/t1driver.h
@@ -18,10 +18,9 @@
#ifndef T1DRIVER_H
#define T1DRIVER_H
-#include <t1objs.h>
-#include <freetype/internal/t1errors.h>
+#include <freetype/internal/ftdriver.h>
- FT_EXPORT_VAR(const FT_DriverInterface) t1z_driver_interface;
+ FT_EXPORT_VAR(const FT_Driver_Class) t1z_driver_class;
#endif /* T1DRIVER_H */
--- a/src/type1z/t1gload.c
+++ b/src/type1z/t1gload.c
@@ -129,9 +129,13 @@
if (glyph)
{
- builder->base = glyph->root.outline;
- builder->max_points = glyph->max_points;
- builder->max_contours = glyph->max_contours;
+ FT_GlyphLoader* loader = glyph->root.loader;
+
+ builder->loader = loader;
+ builder->current = &loader->current.outline;
+ builder->base = &loader->base.outline;
+
+ FT_GlyphLoader_Rewind(loader);
}
if (size)
@@ -147,10 +151,6 @@
builder->left_bearing.y = 0;
builder->advance.x = 0;
builder->advance.y = 0;
-
- builder->base.n_points = 0;
- builder->base.n_contours = 0;
- builder->current = builder->base;
}
@@ -175,11 +175,7 @@
T1_GlyphSlot glyph = builder->glyph;
if (glyph)
- {
- glyph->root.outline = builder->base;
- glyph->max_points = builder->max_points;
- glyph->max_contours = builder->max_contours;
- }
+ glyph->root.outline = *builder->base;
}
@@ -217,39 +213,7 @@
FT_Error check_points( T1_Builder* builder,
FT_Int count )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
-
- if (!builder->load_points)
- return T1_Err_Ok;
-
- count += base->n_points + outline->n_points;
-
- /* realloc points table if necessary */
- if ( count >= builder->max_points )
- {
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->points - base->points;
- FT_Int current = builder->max_points;
-
- while ( builder->max_points < count )
- builder->max_points += 8;
-
- if ( REALLOC_ARRAY( base->points, current,
- builder->max_points, FT_Vector ) ||
-
- REALLOC_ARRAY( base->tags, current,
- builder->max_points, FT_Byte ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->points = base->points + increment;
- outline->tags = base->tags + increment;
- }
- return T1_Err_Ok;
+ return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
}
@@ -260,7 +224,7 @@
FT_Pos y,
FT_Byte flag )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
if (builder->load_points)
{
@@ -298,41 +262,25 @@
static
FT_Error add_contour( T1_Builder* builder )
{
- FT_Outline* base = &builder->base;
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
+ FT_Error error;
if (!builder->load_points)
{
outline->n_contours++;
- return T1_Err_Ok;
+ return FT_Err_Ok;
}
/* realloc contours array if necessary */
- if ( base->n_contours + outline->n_contours >= builder->max_contours &&
- builder->load_points )
+ error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
+ if (!error)
{
- FT_Error error;
- FT_Memory memory = builder->memory;
- FT_Int increment = outline->contours - base->contours;
- FT_Int current = builder->max_contours;
-
- builder->max_contours += 4;
-
- if ( REALLOC_ARRAY( base->contours,
- current, builder->max_contours, FT_Short ) )
- {
- builder->error = error;
- return error;
- }
-
- outline->contours = base->contours + increment;
+ if (outline->n_contours > 0)
+ outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
+
+ outline->n_contours++;
}
-
- if (outline->n_contours > 0)
- outline->contours[ outline->n_contours-1 ] = outline->n_points-1;
-
- outline->n_contours++;
- return T1_Err_Ok;
+ return error;
}
/* if a path was begun, add its first on-curve point */
@@ -358,7 +306,7 @@
static
void close_contour( T1_Builder* builder )
{
- FT_Outline* outline = &builder->current;
+ FT_Outline* outline = builder->current;
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours-1] = outline->n_points-1;
@@ -442,61 +390,37 @@
FT_Int achar )
{
FT_Error error;
- T1_Face face = decoder->builder.face;
FT_Int bchar_index, achar_index, n_base_points;
- FT_Outline* cur = &decoder->builder.current;
- FT_Outline* base = &decoder->builder.base;
+ FT_Outline* cur = decoder->builder.current;
+ FT_Outline* base = decoder->builder.base;
FT_Vector left_bearing, advance;
+ T1_Face face = decoder->builder.face;
T1_Font* type1 = &face->type1;
bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
achar_index = lookup_glyph_by_stdcharcode( face, achar );
- if (bchar_index < 0 || achar_index < 0)
+ if ( bchar_index < 0 || achar_index < 0 )
{
- FT_ERROR(( "T1.Parse_Seac : invalid seac character code arguments\n" ));
+ FT_ERROR(( "t1operator_seac: invalid seac character code arguments\n" ));
return T1_Err_Syntax_Error;
}
- /* First load "bchar" in builder */
- /* now load the unscaled outline */
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
-
- error = T1_Parse_CharStrings( decoder,
- type1->charstrings [bchar_index],
- type1->charstrings_len[bchar_index],
- type1->num_subrs,
- type1->subrs,
- type1->subrs_len );
- if (error) return error;
-
- n_base_points = cur->n_points;
-
+ /* if we are trying to load a composite glyph, do not load the */
+ /* accent character and return the array of subglyphs. */
if ( decoder->builder.no_recurse )
{
- /* if we're trying to load a composite glyph, do not load the */
- /* accent character and return the array of subglyphs.. */
- FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
- FT_SubGlyph* subg;
+ FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
+ FT_GlyphLoader* loader = glyph->loader;
+ FT_SubGlyph* subg;
+
/* reallocate subglyph array if necessary */
- if (glyph->max_subglyphs < 2)
- {
- FT_Memory memory = decoder->builder.face->root.memory;
+ error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
+ if (error) goto Exit;
+
+ subg = loader->current.subglyphs;
- if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
- 2, FT_SubGlyph ) )
- return error;
-
- glyph->max_subglyphs = 2;
- }
-
- subg = glyph->subglyphs;
-
/* subglyph 0 = base character */
subg->index = bchar_index;
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
@@ -514,11 +438,29 @@
/* set up remaining glyph fields */
glyph->num_subglyphs = 2;
glyph->format = ft_glyph_format_composite;
+
+ loader->current.num_subglyphs = 2;
}
- else
+
+ /* First load `bchar' in builder */
+ /* now load the unscaled outline */
+
+ FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */
+
+ error = T1_Parse_CharStrings( decoder,
+ type1->charstrings [bchar_index],
+ type1->charstrings_len[bchar_index],
+ type1->num_subrs,
+ type1->subrs,
+ type1->subrs_len );
+ if ( error ) goto Exit;
+
+ n_base_points = cur->n_points;
+
{
/* save the left bearing and width of the base character */
- /* as they will be erase by the next load.. */
+ /* as they will be erased by the next load. */
+
left_bearing = decoder->builder.left_bearing;
advance = decoder->builder.advance;
@@ -525,15 +467,8 @@
decoder->builder.left_bearing.x = 0;
decoder->builder.left_bearing.y = 0;
- /* Now load "achar" on top of */
+ /* Now load `achar' on top of */
/* the base outline */
- /* */
- cur->n_points = 0;
- cur->n_contours = 0;
- cur->points = base->points + base->n_points;
- cur->tags = base->tags + base->n_points;
- cur->contours = base->contours + base->n_contours;
-
error = T1_Parse_CharStrings( decoder,
type1->charstrings [achar_index],
type1->charstrings_len[achar_index],
@@ -540,27 +475,26 @@
type1->num_subrs,
type1->subrs,
type1->subrs_len );
- if (error) return error;
+ if ( error ) return error;
- /* adjust contours in accented character outline */
- if (decoder->builder.load_points)
- {
- FT_Int n;
-
- for ( n = 0; n < cur->n_contours; n++ )
- cur->contours[n] += n_base_points;
- }
-
/* restore the left side bearing and */
/* advance width of the base character */
+
decoder->builder.left_bearing = left_bearing;
decoder->builder.advance = advance;
/* Finally, move the accent */
- if (decoder->builder.load_points)
- FT_Outline_Translate( cur, adx - asb, ady );
+ if ( decoder->builder.load_points )
+ {
+ FT_Outline dummy;
+
+ dummy.n_points = base->n_points - n_base_points;
+ dummy.points = base->points + n_base_points;
+ FT_Outline_Translate( &dummy, adx - asb, ady );
+ }
}
- return T1_Err_Ok;
+ Exit:
+ return error;
}
@@ -615,7 +549,7 @@
ip = zone->cursor = zone->base;
error = T1_Err_Ok;
- outline = &builder->current;
+ outline = builder->current;
x = builder->pos_x;
y = builder->pos_y;
@@ -922,8 +856,7 @@
close_contour( builder );
/* add current outline to the glyph slot */
- builder->base.n_points += builder->current.n_points;
- builder->base.n_contours += builder->current.n_contours;
+ FT_GlyphLoader_Add( builder->loader );
/* return now !! */
FT_TRACE4(( "\n\n" ));
@@ -1397,7 +1330,7 @@
{
/* scale the outline and the metrics */
FT_Int n;
- FT_Outline* cur = &decoder.builder.base;
+ FT_Outline* cur = decoder.builder.base;
FT_Vector* vec = cur->points;
FT_Fixed x_scale = glyph->x_scale;
FT_Fixed y_scale = glyph->y_scale;
--- a/src/type1z/t1gload.h
+++ b/src/type1z/t1gload.h
@@ -83,34 +83,32 @@
typedef struct T1_Builder_
{
- FT_Memory memory;
- T1_Face face;
- T1_GlyphSlot glyph;
+ FT_Memory memory;
+ T1_Face face;
+ T1_GlyphSlot glyph;
+ FT_GlyphLoader* loader;
- FT_Outline current; /* the current glyph outline */
- FT_Outline base; /* the composite glyph outline */
+ FT_Outline* current; /* the current glyph outline */
+ FT_Outline* base; /* the composite glyph outline */
- FT_Int max_points; /* capacity of base outline in points */
- FT_Int max_contours; /* capacity of base outline in contours */
+ FT_Vector last;
- FT_Vector last;
+ FT_Fixed scale_x;
+ FT_Fixed scale_y;
- FT_Fixed scale_x;
- FT_Fixed scale_y;
+ FT_Pos pos_x;
+ FT_Pos pos_y;
- FT_Pos pos_x;
- FT_Pos pos_y;
+ FT_Vector left_bearing;
+ FT_Vector advance;
- FT_Vector left_bearing;
- FT_Vector advance;
+ FT_BBox bbox; /* bounding box */
+ FT_Bool path_begun;
+ FT_Bool load_points;
+ FT_Bool no_recurse;
- FT_BBox bbox; /* bounding box */
- FT_Bool path_begun;
- FT_Bool load_points;
- FT_Bool no_recurse;
-
- FT_Error error; /* only used for memory errors */
- FT_Bool metrics_only;
+ FT_Error error; /* only used for memory errors */
+ FT_Bool metrics_only;
} T1_Builder;
--- a/src/type1z/t1objs.c
+++ b/src/type1z/t1objs.c
@@ -29,103 +29,6 @@
/*******************************************************************
* *
- * SIZE FUNCTIONS *
- * *
- * *
- *******************************************************************/
-
-/*******************************************************************
- *
- * <Function> T1_Done_Size
- *
- * <Description>
- * The TrueDoc instance object destructor. Used to discard
- * a given instance object..
- *
- * <Input>
- * instance :: handle to the target instance object
- *
- * <Return>
- * TrueDoc error code. 0 means success
- *
- ******************************************************************/
-
- LOCAL_FUNC
- void T1_Done_Size( T1_Size size )
- {
- UNUSED(size);
- }
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_Size
- *
- * <Description>
- * The instance object constructor
- *
- * <Input>
- * instance : handle to new instance object
- * face : pointer to parent face object
- *
- * <Return>
- * TrueDoc error code. 0 means success.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_Size( T1_Size size )
- {
- size->valid = 0;
- return T1_Err_Ok;
- }
-
-
-/*******************************************************************
- *
- * <Function> T1_Reset_Size
- *
- * <Description>
- * Resets an instance to a new pointsize/transform.
- * This function is in charge of resetting the blue zones,
- * As well as the stem snap tables for a given size..
- *
- * <Input>
- * instance the instance object to destroy
- *
- * <Output>
- * Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Reset_Size( T1_Size size )
- {
- /* recompute ascender, descender, etc.. */
- T1_Face face = (T1_Face)size->root.face;
- FT_Size_Metrics* metrics = &size->root.metrics;
-
- if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
- return T1_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 0;
- }
-
-
-/*******************************************************************
- * *
* FACE FUNCTIONS *
* *
* *
@@ -238,16 +141,9 @@
psnames = (PSNames_Interface*)face->psnames;
if (!psnames)
- {
- /* look-up the PSNames driver */
- FT_Driver psnames_driver;
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY(face), "psnames" );
- psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
- if (psnames_driver)
- face->psnames = (PSNames_Interface*)
- (psnames_driver->interface.format_interface);
- }
-
/* open the tokenizer, this will also check the font format */
error = T1_Open_Face( face );
if (error) goto Exit;
@@ -412,57 +308,6 @@
}
Exit:
return error;
- }
-
-
-/*******************************************************************
- *
- * Function : Glyph_Destroy
- *
- * Description : The glyph object destructor.
- *
- * Input : _glyph typeless pointer to the glyph record to destroy
- *
- * Output : Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- void T1_Done_GlyphSlot( T1_GlyphSlot glyph )
- {
- FT_Memory memory = glyph->root.face->memory;
- FT_Library library = glyph->root.face->driver->library;
-
- /* the bitmaps are created on demand */
- FREE( glyph->root.bitmap.buffer );
- FT_Outline_Done( library, &glyph->root.outline );
- return;
- }
-
-
-/*******************************************************************
- *
- * Function : Glyph_Create
- *
- * Description : The glyph object constructor.
- *
- * Input : glyph glyph record to build.
- * face the glyph's parent face.
- *
- * Output : Error code.
- *
- ******************************************************************/
-
- LOCAL_FUNC
- FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph )
- {
- FT_Library library = glyph->root.face->driver->library;
-
- glyph->max_points = 0;
- glyph->max_contours = 0;
- glyph->root.bitmap.buffer = 0;
-
- return FT_Outline_New( library, 0, 0, &glyph->root.outline );
}
--- a/src/type1z/t1objs.h
+++ b/src/type1z/t1objs.h
@@ -170,95 +170,6 @@
void T1_Done_Face( T1_Face face );
-
-/*******************************************************************
- *
- * <Function> T1_Init_Size
- *
- * <Description>
- * Initialise a new Type 1 size object
- *
- * <Input>
- * size :: handle to size object
- *
- * <Return>
- * Type 1 error code. 0 means success.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_Size( T1_Size size );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_Size
- *
- * <Description>
- * The Type 1 size object finaliser.
- *
- * <Input>
- * size :: handle to the target size object.
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_Size( T1_Size size );
-
-
-/*******************************************************************
- *
- * <Function> T1_Reset_Size
- *
- * <Description>
- * Reset a Type 1 size when resolutions and character dimensions
- * have been changed..
- *
- * <Input>
- * size :: handle to the target size object.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Reset_Size( T1_Size size );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Init_GlyphSlot
- *
- * <Description> The TrueType glyph slot initialiser
- *
- * <Input> glyph :: glyph record to build.
- *
- * <Output> Error code.
- *
- ******************************************************************/
-
- LOCAL_DEF
- FT_Error T1_Init_GlyphSlot( T1_GlyphSlot slot );
-
-
-
-/*******************************************************************
- *
- * <Function> T1_Done_GlyphSlot
- *
- * <Description> The Type 1 glyph slot finaliser
- *
- * <Input> glyph :: handle to glyph slot object
- *
- * <Output> Error code.
- *
- ******************************************************************/
-
- LOCAL_DEF
- void T1_Done_GlyphSlot( T1_GlyphSlot slot );
-
-
-
/*******************************************************************
*
* <Function> T1_Init_Driver