ref: b5084e11f7d2d73e0687dee6314c560b8fe6d4cb
parent: 1ea9378ad3e250473464fde4ab336607a958eab1
author: Werner Lemberg <[email protected]>
date: Sat Oct 28 13:10:06 EDT 2000
Renamed z1* files back to t1*; the same transition for Z1_* structures Removed obsolete raster1/* files.
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,8 @@
LATEST CHANGES
+ - "type1z" renamed back to "type1"; the old "type1" module has been
+ removed
+
- revamped the build system to make it a lot more generic. This will
allow us to re-use nearly un-modified in lots of other projects
(including FreeType Layout)
@@ -13,10 +16,10 @@
- updated "docs/docmaker.py", a draft API reference is available at
http://www.freetype.org/ft2api.html
- - changed "type1z" to use "psaux"
+ - changed "type1" to use "psaux"
- created a new module named "psaux" to hold the Type 1 & Type 2 parsing
- routines. It should be used by "type1z", "cid" and "cff" in the future
+ routines. It should be used by "type1", "cid" and "cff" in the future
- fixed an important bug in "FT_Glyph_Get_CBox"
@@ -354,7 +357,7 @@
- changed the default number of gray levels of the smooth renderer to
256 (instead of the previous 128). Of course, the human eye can't
- see any difference ;-)
+ see any difference ;-)
- removed TT_MAX_SUBGLYPHS, there is no static limit on the number of
subglyphs in a TrueType font now..
--- a/docs/BUILD
+++ b/docs/BUILD
@@ -198,7 +198,7 @@
src/sfnt/sfnt.c - the `sfnt' module
src/smooth/smooth.c - the anti-aliasing raster module
src/truetype/truetype.c - the TrueType font driver
- src/type1z/type1z.c - the Type 1 font driver
+ src/type1/type1.c - the Type 1 font driver
The last module of FreeType 2, winfonts (implementing support for
Windows FNT format), is a single file.
--- a/include/freetype/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -86,18 +86,11 @@
trace_t1hint,
trace_t1load,
trace_t1objs,
+ trace_t1parse,
/* PostScript helper module `psaux' */
trace_t1decode,
trace_psobjs,
-
- /* experimental Type 1 driver components */
- trace_z1driver,
- trace_z1gload,
- trace_z1hint,
- trace_z1load,
- trace_z1objs,
- trace_z1parse,
/* Type 2 driver components */
trace_t2driver,
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -59,7 +59,7 @@
#include <freetype/freetype.h>
#include <freetype/internal/ftstream.h>
#include <truetype/ttobjs.h>
-#include <type1z/z1objs.h>
+#include <type1/t1objs.h>
#include <Resources.h>
#include <Fonts.h>
--- a/src/raster1/ftraster.c
+++ /dev/null
@@ -1,3293 +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 */
- /* */
- /*************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-# include "ftraster.h"
-#else
-# include <raster1/ftraster.h>
-#endif
-#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 FT_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
-
-#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_Unsupported -5
-
-
-#else /* _STANDALONE_ */
-
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */
-
-#define Raster_Err_None FT_Err_Ok
-#define Raster_Err_Not_Ini FT_Err_Raster_Uninitialized
-#define Raster_Err_Overflow FT_Err_Raster_Overflow
-#define Raster_Err_Neg_Height FT_Err_Raster_Negative_Height
-#define Raster_Err_Invalid FT_Err_Invalid_Outline
-#define Raster_Err_Unsupported FT_Err_Cannot_Render_Glyph
-
-
-#endif /* _STANDALONE_ */
-
-
- /* 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 FT_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 FT_UNUSED_RASTER FT_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 to be 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;
-
- FT_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;
-
- FT_UNUSED( y );
- FT_UNUSED( left );
- FT_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 */
- FT_UNUSED( raster );
- FT_UNUSED( min );
- FT_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;
-
- FT_UNUSED( left );
- FT_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 */
- FT_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 */
- FT_UNUSED( raster );
- FT_UNUSED( y );
- FT_UNUSED( x1 );
- FT_UNUSED( x2 );
- FT_UNUSED( left );
- FT_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 */
-
- P = draw_left;
- while ( P )
- {
- Q = P->link;
- if ( P->height == 0 )
- DelOld( &draw_left, P );
- P = 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. */
- /* */
- 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 )
- {
- FT_UNUSED_RASTER;
-
- return FT_Err_Cannot_Render_Glyph;
- }
-
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
-
-
- 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;
- }
-
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- /* 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;
-
-#endif
- }
-
-
- /**** 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 )
- {
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING
-
- 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];
- }
-
-#else
-
- FT_UNUSED( raster );
- FT_UNUSED( mode );
- FT_UNUSED( palette );
-
-#endif
- }
-
-
- 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;
-
- /* return immediately if the outline is empty */
- if ( outline->n_points == 0 || outline->n_contours <= 0 )
- return Raster_Err_None;
-
- if ( !outline || !outline->contours || !outline->points )
- return Raster_Err_Invalid;
-
- 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 ) );
- }
-
-
- const 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 */
--- a/src/raster1/ftraster.h
+++ /dev/null
@@ -1,50 +1,0 @@
-/***************************************************************************/
-/* */
-/* 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( const FT_Raster_Funcs ) ft_standard_raster;
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* FTRASTER_H */
-
-
-/* END */
--- a/src/raster1/ftrend1.c
+++ /dev/null
@@ -1,276 +1,0 @@
-/***************************************************************************/
-/* */
-/* ftrend1.c */
-/* */
-/* The FreeType glyph rasterizer 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. */
-/* */
-/***************************************************************************/
-
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/ftoutln.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "ftrend1.h"
-#include "ftraster.h"
-
-#else
-
-#include <raster1/ftrend1.h>
-#include <raster1/ftraster.h>
-
-#endif
-
-
- /* initialize renderer -- init its raster */
- static
- FT_Error ft_raster1_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 FT_Err_Ok;
- }
-
-
- /* set render-specific mode */
- static
- FT_Error ft_raster1_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_raster1_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_raster1_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_raster1_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;
- }
-
- /* check rendering mode */
- if ( mode != ft_render_mode_mono )
- {
- /* raster1 is only capable of producing monochrome bitmaps */
- if ( render->clazz == &ft_raster1_renderer_class )
- return FT_Err_Cannot_Render_Glyph;
- }
- else
- {
- /* raster5 is only capable of producing 5-gray-levels bitmaps */
- if ( render->clazz == &ft_raster5_renderer_class )
- return FT_Err_Cannot_Render_Glyph;
- }
-
- 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 = render->root.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_mono ) )
- {
- /* we pad to 32 bits, only for backwards compatibility with FT 1.x */
- pitch = ( width + 3 ) & -4;
- 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;
- }
-
-
- FT_CPLUSPLUS( const FT_Renderer_Class ) ft_raster1_renderer_class =
- {
- {
- ft_module_renderer,
- sizeof( FT_RendererRec ),
-
- "raster1",
- 0x10000L,
- 0x20000L,
-
- 0, /* module specific interface */
-
- (FT_Module_Constructor)ft_raster1_init,
- (FT_Module_Destructor) 0,
- (FT_Module_Requester) 0
- },
-
- ft_glyph_format_outline,
-
- (FTRenderer_render) ft_raster1_render,
- (FTRenderer_transform)ft_raster1_transform,
- (FTRenderer_getCBox) ft_raster1_get_cbox,
- (FTRenderer_setMode) ft_raster1_set_mode,
-
- (FT_Raster_Funcs*) &ft_standard_raster
- };
-
-
- /* This renderer is _NOT_ part of the default modules; you will need */
- /* to register it by hand in your application. It should only be */
- /* used for backwards-compatibility with FT 1.x anyway. */
- /* */
- FT_CPLUSPLUS( const FT_Renderer_Class ) ft_raster5_renderer_class =
- {
- {
- ft_module_renderer,
- sizeof( FT_RendererRec ),
-
- "raster5",
- 0x10000L,
- 0x20000L,
-
- 0, /* module specific interface */
-
- (FT_Module_Constructor)ft_raster1_init,
- (FT_Module_Destructor) 0,
- (FT_Module_Requester) 0
- },
-
- ft_glyph_format_outline,
-
- (FTRenderer_render) ft_raster1_render,
- (FTRenderer_transform)ft_raster1_transform,
- (FTRenderer_getCBox) ft_raster1_get_cbox,
- (FTRenderer_setMode) ft_raster1_set_mode,
-
- (FT_Raster_Funcs*) &ft_standard_raster
- };
-
-
-/* END */
--- a/src/raster1/ftrend1.h
+++ /dev/null
@@ -1,48 +1,0 @@
-/***************************************************************************/
-/* */
-/* ftrend1.h */
-/* */
-/* The FreeType glyph rasterizer 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. */
-/* */
-/***************************************************************************/
-
-
-#ifndef FTREND1_H
-#define FTREND1_H
-
-
-#include <freetype/ftrender.h>
-
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster1_renderer_class;
-
- /* this renderer is _NOT_ part of the default modules, you'll need */
- /* to register it by hand in your application. It should only be */
- /* used for backwards-compatibility with FT 1.x anyway. */
- /* */
- FT_EXPORT_VAR( const FT_Renderer_Class ) ft_raster5_renderer_class;
-
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* FTREND1_H */
-
-
-/* END */
--- a/src/raster1/raster1.c
+++ /dev/null
@@ -1,35 +1,0 @@
-/***************************************************************************/
-/* */
-/* raster1.c */
-/* */
-/* FreeType monochrome rasterer module 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
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "ftraster.c"
-#include "ftrend1.c"
-
-#else
-
-#include <raster1/ftraster.c>
-#include <raster1/ftrend1.c>
-
-#endif
-
-
-/* END */
--- a/src/type1/module.mk
+++ b/src/type1/module.mk
@@ -1,5 +1,5 @@
#
-# FreeType 2 Type1z module definition
+# FreeType 2 Type1 module definition
#
--- a/src/type1/rules.mk
+++ b/src/type1/rules.mk
@@ -1,5 +1,5 @@
#
-# FreeType 2 Type1z driver configuration rules
+# FreeType 2 Type1 driver configuration rules
#
@@ -26,20 +26,20 @@
# Type1 driver sources (i.e., C files)
#
-T1_DRV_SRC := $(T1_DIR_)z1parse.c \
- $(T1_DIR_)z1load.c \
- $(T1_DIR_)z1driver.c \
- $(T1_DIR_)z1afm.c \
- $(T1_DIR_)z1gload.c \
- $(T1_DIR_)z1objs.c
+T1_DRV_SRC := $(T1_DIR_)t1parse.c \
+ $(T1_DIR_)t1load.c \
+ $(T1_DIR_)t1driver.c \
+ $(T1_DIR_)t1afm.c \
+ $(T1_DIR_)t1gload.c \
+ $(T1_DIR_)t1objs.c
# Type1 driver headers
#
T1_DRV_H := $(T1_DRV_SRC:%.c=%.h) \
- $(T1_DIR_)z1tokens.h
+ $(T1_DIR_)t1tokens.h
-# Type1z driver object(s)
+# Type1 driver object(s)
#
# T1_DRV_OBJ_M is used during `multi' builds
# T1_DRV_OBJ_S is used during `single' builds
@@ -47,18 +47,18 @@
T1_DRV_OBJ_M := $(T1_DRV_SRC:$(T1_DIR_)%.c=$(OBJ_)%.$O)
T1_DRV_OBJ_S := $(OBJ_)type1.$O
-# Type1z driver source file for single build
+# Type1 driver source file for single build
#
T1_DRV_SRC_S := $(T1_DIR_)type1.c
-# Type1z driver - single object
+# Type1 driver - single object
#
$(T1_DRV_OBJ_S): $(T1_DRV_SRC_S) $(T1_DRV_SRC) $(FREETYPE_H) $(T1_DRV_H)
$(T1_COMPILE) $T$@ $(T1_DRV_SRC_S)
-# Type1z driver - multiple objects
+# Type1 driver - multiple objects
#
$(OBJ_)%.$O: $(T1_DIR_)%.c $(FREETYPE_H) $(T1_DRV_H)
$(T1_COMPILE) $T$@ $<
--- /dev/null
+++ b/src/type1/t1afm.c
@@ -1,0 +1,293 @@
+/***************************************************************************/
+/* */
+/* t1afm.c */
+/* */
+/* AFM support for Type 1 fonts (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. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1types.h>
+
+#include <stdlib.h> /* for qsort() */
+#include <string.h> /* for strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* 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_t1afm
+
+
+ LOCAL_FUNC
+ void T1_Done_AFM( FT_Memory memory,
+ T1_AFM* afm )
+ {
+ FREE( afm->kern_pairs );
+ afm->num_pairs = 0;
+ }
+
+
+#undef IS_KERN_PAIR
+#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' )
+
+#define IS_ALPHANUM( c ) ( isalnum( c ) || \
+ c == '_' || \
+ c == '.' )
+
+
+ /* read a glyph name and return the equivalent glyph index */
+ static
+ FT_UInt afm_atoindex( FT_Byte** start,
+ FT_Byte* limit,
+ T1_Font* type1 )
+ {
+ FT_Byte* p = *start;
+ FT_Int len;
+ FT_UInt result = 0;
+ char temp[64];
+
+
+ /* skip whitespace */
+ while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
+ p < limit )
+ p++;
+ *start = p;
+
+ /* now, read glyph name */
+ while ( IS_ALPHANUM( *p ) && p < limit )
+ p++;
+
+ len = p - *start;
+
+ if ( len > 0 && len < 64 )
+ {
+ FT_Int n;
+
+
+ /* copy glyph name to intermediate array */
+ MEM_Copy( temp, *start, len );
+ temp[len] = 0;
+
+ /* lookup glyph name in face array */
+ for ( n = 0; n < type1->num_glyphs; n++ )
+ {
+ char* gname = (char*)type1->glyph_names[n];
+
+
+ if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ *start = p;
+ return result;
+ }
+
+
+ /* read an integer */
+ static
+ int afm_atoi( FT_Byte** start,
+ FT_Byte* limit )
+ {
+ FT_Byte* p = *start;
+ int sum = 0;
+ int sign = 1;
+
+
+ /* skip everything that is not a number */
+ while ( p < limit && !isdigit( *p ) )
+ {
+ sign = 1;
+ if ( *p == '-' )
+ sign = -1;
+
+ p++;
+ }
+
+ while ( p < limit && isdigit( *p ) )
+ {
+ sum = sum * 10 + ( *p - '0' );
+ p++;
+ }
+ *start = p;
+
+ return sum * sign;
+ }
+
+
+#undef KERN_INDEX
+#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
+
+
+ /* compare two kerning pairs */
+ LOCAL_FUNC_X
+ int compare_kern_pairs( const void* a,
+ const void* b )
+ {
+ T1_Kern_Pair* pair1 = (T1_Kern_Pair*)a;
+ T1_Kern_Pair* pair2 = (T1_Kern_Pair*)b;
+
+ FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
+ FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
+
+
+ return ( index1 - index2 );
+ }
+
+
+ /* parse an AFM file -- for now, only read the kerning pairs */
+ LOCAL_FUNC
+ FT_Error T1_Read_AFM( FT_Face t1_face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = stream->memory;
+ FT_Byte* start;
+ FT_Byte* limit;
+ FT_Byte* p;
+ FT_Int count = 0;
+ T1_Kern_Pair* pair;
+ T1_Font* type1 = &((T1_Face)t1_face)->type1;
+ T1_AFM* afm = 0;
+
+
+ if ( ACCESS_Frame( stream->size ) )
+ return error;
+
+ start = (FT_Byte*)stream->cursor;
+ limit = (FT_Byte*)stream->limit;
+ p = start;
+
+ /* we are now going to count the occurences of `KP' or `KPX' in */
+ /* the AFM file */
+ count = 0;
+ for ( p = start; p < limit - 3; p++ )
+ {
+ if ( IS_KERN_PAIR( p ) )
+ count++;
+ }
+
+ /* Actually, kerning pairs are simply optional! */
+ if ( count == 0 )
+ goto Exit;
+
+ /* allocate the pairs */
+ if ( ALLOC( afm, sizeof ( *afm ) ) ||
+ ALLOC_ARRAY( afm->kern_pairs, count, T1_Kern_Pair ) )
+ goto Exit;
+
+ /* now, read each kern pair */
+ pair = afm->kern_pairs;
+ afm->num_pairs = count;
+
+ /* save in face object */
+ ((T1_Face)t1_face)->afm_data = afm;
+
+ for ( p = start; p < limit - 3; p++ )
+ {
+ if ( IS_KERN_PAIR( p ) )
+ {
+ FT_Byte* q;
+
+
+ /* skip keyword (KP or KPX) */
+ q = p + 2;
+ if ( *q == 'X' )
+ q++;
+
+ pair->glyph1 = afm_atoindex( &q, limit, type1 );
+ pair->glyph2 = afm_atoindex( &q, limit, type1 );
+ pair->kerning.x = afm_atoi( &q, limit );
+
+ pair->kerning.y = 0;
+ if ( p[2] != 'X' )
+ pair->kerning.y = afm_atoi( &q, limit );
+
+ pair++;
+ }
+ }
+
+ /* now, sort the kern pairs according to their glyph indices */
+ qsort( afm->kern_pairs, count, sizeof ( T1_Kern_Pair ),
+ compare_kern_pairs );
+
+ Exit:
+ if ( error )
+ FREE( afm );
+
+ FORGET_Frame();
+
+ return error;
+ }
+
+
+ /* find the kerning for a given glyph pair */
+ LOCAL_FUNC
+ void T1_Get_Kerning( T1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning )
+ {
+ T1_Kern_Pair *min, *mid, *max;
+ FT_ULong index = KERN_INDEX( glyph1, glyph2 );
+
+
+ /* simple binary search */
+ min = afm->kern_pairs;
+ max = min + afm->num_pairs - 1;
+
+ while ( min <= max )
+ {
+ FT_ULong midi;
+
+
+ mid = min + ( max - min ) / 2;
+ midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
+
+ if ( midi == index )
+ {
+ *kerning = mid->kerning;
+ return;
+ }
+
+ if ( midi < index )
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ kerning->x = 0;
+ kerning->y = 0;
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1afm.h
@@ -1,0 +1,79 @@
+/***************************************************************************/
+/* */
+/* 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. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1AFM_H
+#define T1AFM_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ typedef struct T1_Kern_Pair_
+ {
+ FT_UInt glyph1;
+ FT_UInt glyph2;
+ FT_Vector kerning;
+
+ } T1_Kern_Pair;
+
+
+ typedef struct T1_AFM_
+ {
+ FT_Int num_pairs;
+ T1_Kern_Pair* kern_pairs;
+
+ } T1_AFM;
+
+
+ LOCAL_DEF
+ FT_Error T1_Read_AFM( FT_Face face,
+ FT_Stream stream );
+
+ LOCAL_DEF
+ void T1_Done_AFM( FT_Memory memory,
+ T1_AFM* afm );
+
+ LOCAL_DEF
+ void T1_Get_Kerning( T1_AFM* afm,
+ FT_UInt glyph1,
+ FT_UInt glyph2,
+ FT_Vector* kerning );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1AFM_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1driver.c
@@ -1,0 +1,340 @@
+/***************************************************************************/
+/* */
+/* 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. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1driver.h"
+#include "t1gload.h"
+#include "t1load.h"
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1driver.h>
+#include <type1/t1gload.h>
+#include <type1/t1load.h>
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psnames.h>
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* 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
+
+
+ static
+ FT_Error get_t1_glyph_name( T1_Face face,
+ FT_UInt glyph_index,
+ FT_Pointer buffer,
+ FT_UInt buffer_max )
+ {
+ FT_String* gname;
+
+
+ gname = face->type1.glyph_names[glyph_index];
+
+ if ( buffer_max > 0 )
+ {
+ FT_UInt len = strlen( gname );
+
+
+ if (len >= buffer_max)
+ len = buffer_max - 1;
+
+ MEM_Copy( buffer, gname, len );
+ ((FT_Byte*)buffer)[len] = 0;
+ }
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Interface */
+ /* */
+ /* <Description> */
+ /* Each driver can provide one or more extensions to the base */
+ /* FreeType API. These can be used to access format specific */
+ /* features (e.g., all TrueType/OpenType resources share a common */
+ /* file structure and common tables which can be accessed through the */
+ /* `sfnt' interface), or more simply generic ones (e.g., the */
+ /* `postscript names' interface which can be used to retrieve the */
+ /* PostScript name of a given glyph index). */
+ /* */
+ /* <InOut> */
+ /* driver :: A handle to a driver object. */
+ /* */
+ /* <Input> */
+ /* interface :: A string designing the interface. Examples are */
+ /* `sfnt', `post_names', `charmaps', etc. */
+ /* */
+ /* <Return> */
+ /* A typeless pointer to the extension's interface (normally a table */
+ /* of function pointers). Returns NULL if the requested extension */
+ /* isn't available (i.e., wasn't compiled in the driver at build */
+ /* time). */
+ /* */
+ static
+ FT_Module_Interface Get_Interface( FT_Driver driver,
+ const FT_String* interface )
+ {
+ FT_UNUSED( driver );
+ FT_UNUSED( interface );
+
+ if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
+ return (FT_Module_Interface)get_t1_glyph_name;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
+ return (FT_Module_Interface)T1_Get_Multi_Master;
+
+ if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
+ return (FT_Module_Interface)T1_Set_MM_Design;
+
+ if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
+ return (FT_Module_Interface)T1_Set_MM_Blend;
+#endif
+ return 0;
+ }
+
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Kerning */
+ /* */
+ /* <Description> */
+ /* A driver method used to return the kerning vector between two */
+ /* glyphs of the same face. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* left_glyph :: The index of the left glyph in the kern pair. */
+ /* */
+ /* right_glyph :: The index of the right glyph in the kern pair. */
+ /* */
+ /* <Output> */
+ /* kerning :: The kerning vector. This is in font units for */
+ /* scalable formats, and in pixels for fixed-sizes */
+ /* formats. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ /* <Note> */
+ /* Only horizontal layouts (left-to-right & right-to-left) are */
+ /* supported by this function. Other layouts, or more sophisticated */
+ /* kernings are out of scope of this method (the basic driver */
+ /* interface is meant to be simple). */
+ /* */
+ /* They can be implemented by format-specific interfaces. */
+ /* */
+ static
+ FT_Error Get_Kerning( T1_Face face,
+ FT_UInt left_glyph,
+ FT_UInt right_glyph,
+ FT_Vector* kerning )
+ {
+ T1_AFM* afm;
+
+
+ kerning->x = 0;
+ kerning->y = 0;
+
+ afm = (T1_AFM*)face->afm_data;
+ if ( afm )
+ T1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
+
+ return T1_Err_Ok;
+ }
+
+
+#endif /* T1_CONFIG_OPTION_NO_AFM */
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Char_Index */
+ /* */
+ /* <Description> */
+ /* Uses a charmap to return a given character code's glyph index. */
+ /* */
+ /* <Input> */
+ /* charmap :: A handle to the source charmap object. */
+ /* charcode :: The character code. */
+ /* */
+ /* <Return> */
+ /* Glyph index. 0 means `undefined character code'. */
+ /* */
+ static
+ FT_UInt Get_Char_Index( FT_CharMap charmap,
+ FT_Long charcode )
+ {
+ T1_Face face;
+ FT_UInt result = 0;
+ PSNames_Interface* psnames;
+
+
+ face = (T1_Face)charmap->face;
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( psnames )
+ switch ( charmap->encoding )
+ {
+ /*******************************************************************/
+ /* */
+ /* Unicode encoding support */
+ /* */
+ case ft_encoding_unicode:
+ /* use the `PSNames' module to synthetize the Unicode charmap */
+ result = psnames->lookup_unicode( &face->unicode_map,
+ (FT_ULong)charcode );
+
+ /* the function returns 0xFFFF if the Unicode charcode has */
+ /* no corresponding glyph */
+ if ( result == 0xFFFF )
+ result = 0;
+ goto Exit;
+
+ /*******************************************************************/
+ /* */
+ /* Custom Type 1 encoding */
+ /* */
+ case ft_encoding_adobe_custom:
+ {
+ T1_Encoding* encoding = &face->type1.encoding;
+
+
+ if ( charcode >= encoding->code_first &&
+ charcode <= encoding->code_last )
+ result = encoding->char_index[charcode];
+ goto Exit;
+ }
+
+ /*******************************************************************/
+ /* */
+ /* Adobe Standard & Expert encoding support */
+ /* */
+ default:
+ if ( charcode < 256 )
+ {
+ FT_UInt code;
+ FT_Int n;
+ const char* glyph_name;
+
+
+ code = psnames->adobe_std_encoding[charcode];
+ if ( charmap->encoding == ft_encoding_adobe_expert )
+ code = psnames->adobe_expert_encoding[charcode];
+
+ glyph_name = psnames->adobe_std_strings( code );
+ if ( !glyph_name )
+ break;
+
+ for ( n = 0; n < face->type1.num_glyphs; n++ )
+ {
+ const char* gname = face->type1.glyph_names[n];
+
+
+ if ( gname && gname[0] == glyph_name[0] &&
+ strcmp( gname, glyph_name ) == 0 )
+ {
+ result = n;
+ break;
+ }
+ }
+ }
+ }
+ Exit:
+ return result;
+ }
+
+
+ FT_CPLUSPLUS( const FT_Driver_Class ) t1_driver_class =
+ {
+ {
+ ft_module_font_driver | ft_module_driver_scalable,
+ sizeof( FT_DriverRec ),
+
+ "type1",
+ 0x10000L,
+ 0x20000L,
+
+ 0, /* format interface */
+
+ (FT_Module_Constructor)T1_Init_Driver,
+ (FT_Module_Destructor) T1_Done_Driver,
+ (FT_Module_Requester) Get_Interface,
+ },
+
+ sizeof( T1_FaceRec ),
+ sizeof( T1_SizeRec ),
+ sizeof( T1_GlyphSlotRec ),
+
+ (FTDriver_initFace) T1_Init_Face,
+ (FTDriver_doneFace) T1_Done_Face,
+ (FTDriver_initSize) 0,
+ (FTDriver_doneSize) 0,
+ (FTDriver_initGlyphSlot)0,
+ (FTDriver_doneGlyphSlot)0,
+
+ (FTDriver_setCharSizes) 0,
+ (FTDriver_setPixelSizes)0,
+ (FTDriver_loadGlyph) T1_Load_Glyph,
+ (FTDriver_getCharIndex) Get_Char_Index,
+
+#ifdef T1_CONFIG_OPTION_NO_AFM
+ (FTDriver_getKerning) 0,
+ (FTDriver_attachFile) 0,
+#else
+ (FTDriver_getKerning) Get_Kerning,
+ (FTDriver_attachFile) T1_Read_AFM,
+#endif
+ (FTDriver_getAdvances) 0
+ };
+
+
+#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
+
+ EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
+ {
+ return &t1_driver_class;
+ }
+
+#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1driver.h
@@ -1,0 +1,39 @@
+/***************************************************************************/
+/* */
+/* 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. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1DRIVER_H
+#define T1DRIVER_H
+
+#include <freetype/internal/ftdriver.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class;
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1DRIVER_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1gload.c
@@ -1,0 +1,309 @@
+/***************************************************************************/
+/* */
+/* 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. */
+/* */
+/***************************************************************************/
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+
+#else
+
+#include <type1/t1gload.h>
+
+#endif
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/ftoutln.h>
+#include <freetype/internal/psaux.h>
+
+
+#include <string.h> /* for strcmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* 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
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /********** *********/
+ /********** 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. *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC_X
+ FT_Error T1_Parse_Glyph( T1_Decoder* decoder,
+ FT_UInt glyph_index )
+ {
+ T1_Face face = (T1_Face)decoder->builder.face;
+ T1_Font* type1 = &face->type1;
+
+
+ decoder->font_matrix = type1->font_matrix;
+ decoder->font_offset = type1->font_offset;
+
+ return decoder->funcs.parse_charstrings(
+ decoder,
+ type1->charstrings [glyph_index],
+ type1->charstrings_len[glyph_index] );
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance )
+ {
+ FT_Error error;
+ T1_Decoder decoder;
+ FT_Int glyph_index;
+ T1_Font* type1 = &face->type1;
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+
+
+ *max_advance = 0;
+
+ /* initialize load decoder */
+ error = psaux->t1_decoder_funcs->init( &decoder,
+ (FT_Face)face,
+ 0, /* size */
+ 0, /* glyph slot */
+ (FT_Byte**)type1->glyph_names,
+ face->blend,
+ T1_Parse_Glyph );
+ if ( error )
+ return error;
+
+ decoder.builder.metrics_only = 1;
+ decoder.builder.load_points = 0;
+
+ decoder.num_subrs = type1->num_subrs;
+ decoder.subrs = type1->subrs;
+ decoder.subrs_len = type1->subrs_len;
+
+ /* for each glyph, parse the glyph charstring and extract */
+ /* the advance width */
+ for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
+ {
+ /* now get load the unscaled outline */
+ error = T1_Parse_Glyph( &decoder, glyph_index );
+ /* ignore the error if one occured - skip to next glyph */
+ }
+
+ *max_advance = decoder.builder.advance.x;
+ return FT_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' *********/
+ /********** *********/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ LOCAL_FUNC
+ FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags )
+ {
+ FT_Error error;
+ T1_Decoder decoder;
+ T1_Face face = (T1_Face)glyph->root.face;
+ FT_Bool hinting;
+ T1_Font* type1 = &face->type1;
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+ const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
+
+ FT_Matrix font_matrix;
+ FT_Vector font_offset;
+
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
+ glyph->x_scale = size->root.metrics.x_scale;
+ glyph->y_scale = size->root.metrics.y_scale;
+
+ glyph->root.outline.n_points = 0;
+ glyph->root.outline.n_contours = 0;
+
+ hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
+ ( load_flags & FT_LOAD_NO_HINTING ) == 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ error = decoder_funcs->init( &decoder,
+ (FT_Face)face,
+ (FT_Size)size,
+ (FT_GlyphSlot)glyph,
+ (FT_Byte**)type1->glyph_names,
+ face->blend,
+ T1_Parse_Glyph );
+ if ( error )
+ goto Exit;
+
+ decoder.builder.no_recurse = ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
+
+ decoder.num_subrs = type1->num_subrs;
+ decoder.subrs = type1->subrs;
+ decoder.subrs_len = type1->subrs_len;
+
+
+ /* now load the unscaled outline */
+ error = T1_Parse_Glyph( &decoder, glyph_index );
+ if ( error )
+ goto Exit;
+
+ font_matrix = decoder.font_matrix;
+ font_offset = decoder.font_offset;
+
+ /* save new glyph tables */
+ decoder_funcs->done( &decoder );
+
+ /* 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 )
+ {
+ glyph->root.outline.flags &= ft_outline_owner;
+ glyph->root.outline.flags |= ft_outline_reverse_fill;
+
+ /* for composite glyphs, return only left side bearing and */
+ /* advance width */
+ if ( load_flags & FT_LOAD_NO_RECURSE )
+ {
+ glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+ glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
+ }
+ else
+ {
+ FT_BBox cbox;
+ FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+
+
+ /* copy the _unscaled_ advance width */
+ metrics->horiAdvance = decoder.builder.advance.x;
+ glyph->root.linearHoriAdvance = decoder.builder.advance.x;
+
+ /* make up vertical metrics */
+ metrics->vertBearingX = 0;
+ metrics->vertBearingY = 0;
+ metrics->vertAdvance = 0;
+
+ glyph->root.linearVertAdvance = 0;
+
+ glyph->root.format = ft_glyph_format_outline;
+
+ if ( size && size->root.metrics.y_ppem < 24 )
+ glyph->root.outline.flags |= ft_outline_high_precision;
+
+ /* apply the font matrix */
+ FT_Outline_Transform( &glyph->root.outline, &font_matrix );
+
+ FT_Outline_Translate( &glyph->root.outline,
+ font_offset.x,
+ font_offset.y );
+
+#if 0
+
+ glyph->root.outline.second_pass = TRUE;
+ glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
+ glyph->root.outline.dropout_mode = 2;
+
+#endif /* 0 */
+
+ if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
+ {
+ /* scale the outline and the metrics */
+ FT_Int n;
+ FT_Outline* cur = decoder.builder.base;
+ FT_Vector* vec = cur->points;
+ FT_Fixed x_scale = glyph->x_scale;
+ FT_Fixed y_scale = glyph->y_scale;
+
+
+ /* First of all, scale the points */
+ for ( n = cur->n_points; n > 0; n--, vec++ )
+ {
+ vec->x = FT_MulFix( vec->x, x_scale );
+ vec->y = FT_MulFix( vec->y, y_scale );
+ }
+
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* Then scale the metrics */
+ metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
+ metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
+
+ metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+ metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+ }
+
+ /* compute the other metrics */
+ FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+
+ /* grid fit the bounding box if necessary */
+ if ( hinting )
+ {
+ cbox.xMin &= -64;
+ cbox.yMin &= -64;
+ cbox.xMax = ( cbox.xMax+63 ) & -64;
+ cbox.yMax = ( cbox.yMax+63 ) & -64;
+ }
+
+ metrics->width = cbox.xMax - cbox.xMin;
+ metrics->height = cbox.yMax - cbox.yMin;
+
+ metrics->horiBearingX = cbox.xMin;
+ metrics->horiBearingY = cbox.yMax;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1gload.h
@@ -1,0 +1,58 @@
+/***************************************************************************/
+/* */
+/* 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. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1GLOAD_H
+#define T1GLOAD_H
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1objs.h"
+
+#else
+
+#include <type1/t1objs.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ LOCAL_DEF
+ FT_Error T1_Compute_Max_Advance( T1_Face face,
+ FT_Int* max_advance );
+
+ LOCAL_DEF
+ FT_Error T1_Load_Glyph( T1_GlyphSlot glyph,
+ T1_Size size,
+ FT_Int glyph_index,
+ FT_Int load_flags );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1GLOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1load.c
@@ -1,0 +1,1702 @@
+/***************************************************************************/
+/* */
+/* t1load.c */
+/* */
+/* Type 1 font 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. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* This is the new and improved Type 1 data loader for FreeType 2. The */
+ /* old loader has several problems: it is slow, complex, difficult to */
+ /* maintain, and contains incredible hacks to make it accept some */
+ /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
+ /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
+ /* */
+ /* This version is much simpler, much faster and also easier to read and */
+ /* maintain by a great order of magnitude. The idea behind it is to */
+ /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
+ /* a Postscript-like interpreter) but rather to perform simple pattern */
+ /* matching. */
+ /* */
+ /* Indeed, nearly all data definitions follow a simple pattern like */
+ /* */
+ /* ... /Field <data> ... */
+ /* */
+ /* where <data> can be a number, a boolean, a string, or an array of */
+ /* numbers. There are a few exceptions, namely the encoding, font name, */
+ /* charstrings, and subrs; they are handled with a special pattern */
+ /* matching routine. */
+ /* */
+ /* All other common cases are handled very simply. The matching rules */
+ /* are defined in the file `t1tokens.h' through the use of several */
+ /* macros calls PARSE_XXX. */
+ /* */
+ /* This file is included twice here; the first time to generate parsing */
+ /* callback functions, the second to generate a table of keywords (with */
+ /* pointers to the associated callback). */
+ /* */
+ /* The function `parse_dict' simply scans *linearly* a given dictionary */
+ /* (either the top-level or private one) and calls the appropriate */
+ /* callback when it encounters an immediate keyword. */
+ /* */
+ /* This is by far the fastest way one can find to parse and read all */
+ /* data. */
+ /* */
+ /* This led to tremendous code size reduction. Note that later, the */
+ /* glyph loader will also be _greatly_ simplified, and the automatic */
+ /* hinter will replace the clumsy `t1hinter'. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/ftmm.h>
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/t1errors.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1load.h"
+
+#else
+
+#include <type1/t1load.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp(), strcmp() */
+#include <ctype.h> /* for isalnum() */
+
+
+ /*************************************************************************/
+ /* */
+ /* 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_t1load
+
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** MULTIPLE MASTERS SUPPORT *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+ static
+ FT_Error t1_allocate_blend( T1_Face face,
+ FT_UInt num_designs,
+ FT_UInt num_axis )
+ {
+ T1_Blend* blend;
+ FT_Memory memory = face->root.memory;
+ FT_Error error = 0;
+
+
+ blend = face->blend;
+ if ( !blend )
+ {
+ if ( ALLOC( blend, sizeof ( *blend ) ) )
+ goto Exit;
+
+ face->blend = blend;
+ }
+
+ /* allocate design data if needed */
+ if ( num_designs > 0 )
+ {
+ if ( blend->num_designs == 0 )
+ {
+ FT_UInt nn;
+
+
+ /* allocate the blend `private' and `font_info' dictionaries */
+ if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
+ ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
+ ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
+ goto Exit;
+
+ blend->default_weight_vector = blend->weight_vector + num_designs;
+
+ blend->font_infos[0] = &face->type1.font_info;
+ blend->privates [0] = &face->type1.private_dict;
+
+ for ( nn = 2; nn <= num_designs; nn++ )
+ {
+ blend->privates[nn] = blend->privates [nn - 1] + 1;
+ blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
+ }
+
+ blend->num_designs = num_designs;
+ }
+ else if ( blend->num_designs != num_designs )
+ goto Fail;
+ }
+
+ /* allocate axis data if needed */
+ if ( num_axis > 0 )
+ {
+ if ( blend->num_axis != 0 && blend->num_axis != num_axis )
+ goto Fail;
+
+ blend->num_axis = num_axis;
+ }
+
+ /* allocate the blend design pos table if needed */
+ num_designs = blend->num_designs;
+ num_axis = blend->num_axis;
+ if ( num_designs && num_axis && blend->design_pos[0] == 0 )
+ {
+ FT_UInt n;
+
+
+ if ( ALLOC_ARRAY( blend->design_pos[0],
+ num_designs * num_axis, FT_Fixed ) )
+ goto Exit;
+
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
+ }
+
+ Exit:
+ return error;
+
+ Fail:
+ error = -1;
+ goto Exit;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master )
+ {
+ T1_Blend* blend = face->blend;
+ FT_UInt n;
+ FT_Error error;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend )
+ {
+ master->num_axis = blend->num_axis;
+ master->num_designs = blend->num_designs;
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_MM_Axis* axis = master->axis + n;
+ T1_DesignMap* map = blend->design_map + n;
+
+
+ axis->name = blend->axis_names[n];
+ axis->minimum = map->design_points[0];
+ axis->maximum = map->design_points[map->num_points - 1];
+ }
+ error = 0;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, m;
+
+
+ error = T1_Err_Invalid_Argument;
+
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* recompute the weight vector from the blend coordinates */
+ error = FT_Err_Ok;
+
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ FT_Fixed result = 0x10000L; /* 1.0 fixed */
+
+
+ for ( m = 0; m < blend->num_axis; m++ )
+ {
+ FT_Fixed factor;
+
+
+ /* get current blend axis position */
+ factor = coords[m];
+ if ( factor < 0 ) factor = 0;
+ if ( factor > 0x10000L ) factor = 0x10000L;
+
+ if ( ( n & ( 1 << m ) ) == 0 )
+ factor = 0x10000L - factor;
+
+ result = FT_MulFix( result, factor );
+ }
+ blend->weight_vector[n] = result;
+ }
+
+ error = FT_Err_Ok;
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords )
+ {
+ T1_Blend* blend = face->blend;
+ FT_Error error;
+ FT_UInt n, p;
+
+
+ error = T1_Err_Invalid_Argument;
+ if ( blend && blend->num_axis == num_coords )
+ {
+ /* compute the blend coordinates through the blend design map */
+ FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
+
+
+ for ( n = 0; n < blend->num_axis; n++ )
+ {
+ FT_Long design = coords[n];
+ FT_Fixed the_blend;
+ T1_DesignMap* map = blend->design_map + n;
+ FT_Fixed* designs = map->design_points;
+ FT_Fixed* blends = map->blend_points;
+ FT_Int before = -1, after = -1;
+
+ for ( p = 0; p < map->num_points; p++ )
+ {
+ FT_Fixed p_design = designs[p];
+
+
+ /* exact match ? */
+ if ( design == p_design )
+ {
+ the_blend = blends[p];
+ goto Found;
+ }
+
+ if ( design < p_design )
+ {
+ after = p;
+ break;
+ }
+
+ before = p;
+ }
+
+ /* now, interpolate if needed */
+ if ( before < 0 )
+ the_blend = blends[0];
+
+ else if ( after < 0 )
+ the_blend = blends[map->num_points - 1];
+
+ else
+ the_blend = FT_MulDiv( design - designs[before],
+ blends [after] - blends [before],
+ designs[after] - designs[before] );
+
+ Found:
+ final_blends[n] = the_blend;
+ }
+
+ error = T1_Set_MM_Blend( face, num_coords, final_blends );
+ }
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void T1_Done_Blend( T1_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ T1_Blend* blend = face->blend;
+
+
+ if ( blend )
+ {
+ FT_UInt num_designs = blend->num_designs;
+ FT_UInt num_axis = blend->num_axis;
+ FT_UInt n;
+
+
+ /* release design pos table */
+ FREE( blend->design_pos[0] );
+ for ( n = 1; n < num_designs; n++ )
+ blend->design_pos[n] = 0;
+
+ /* release blend `private' and `font info' dictionaries */
+ FREE( blend->privates[1] );
+ FREE( blend->font_infos[1] );
+
+ for ( n = 0; n < num_designs; n++ )
+ {
+ blend->privates [n] = 0;
+ blend->font_infos[n] = 0;
+ }
+
+ /* release weight vectors */
+ FREE( blend->weight_vector );
+ blend->default_weight_vector = 0;
+
+ /* release axis names */
+ for ( n = 0; n < num_axis; n++ )
+ FREE( blend->axis_names[n] );
+
+ /* release design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* dmap = blend->design_map + n;
+
+
+ FREE( dmap->design_points );
+ dmap->num_points = 0;
+ }
+
+ FREE( face->blend );
+ }
+ }
+
+
+ static
+ void parse_blend_axis_types( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_Token axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Error error = 0;
+ T1_Blend* blend;
+ FT_Memory memory;
+
+
+ /* take an array of objects */
+ T1_ToTokenArray( &loader->parser, axis_tokens,
+ T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate blend if necessary */
+ error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
+ if ( error )
+ goto Exit;
+
+ blend = face->blend;
+ memory = face->root.memory;
+
+ /* each token is an immediate containing the name of the axis */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_Token* token = axis_tokens + n;
+ FT_Byte* name;
+ FT_Int len;
+
+ /* skip first slash, if any */
+ if (token->start[0] == '/')
+ token->start++;
+
+ len = token->limit - token->start;
+ if ( len <= 0 )
+ {
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ if ( ALLOC( blend->axis_names[n], len + 1 ) )
+ goto Exit;
+
+ name = (FT_Byte*)blend->axis_names[n];
+ MEM_Copy( name, token->start, len );
+ name[len] = 0;
+ }
+
+ Exit:
+ loader->parser.root.error = error;
+ }
+
+
+ static
+ void parse_blend_design_positions( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_Token design_tokens[ T1_MAX_MM_DESIGNS ];
+ FT_Int num_designs;
+ FT_Int num_axis;
+ T1_ParserRec* parser = &loader->parser;
+
+ FT_Error error = 0;
+ T1_Blend* blend;
+
+
+ /* get the array of design tokens - compute number of designs */
+ T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
+ if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
+ {
+ FT_ERROR(( "parse_blend_design_positions:" ));
+ FT_ERROR(( " incorrect number of designs: %d\n",
+ num_designs ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ {
+ FT_Byte* old_cursor = parser->root.cursor;
+ FT_Byte* old_limit = parser->root.limit;
+ FT_UInt n;
+
+
+ blend = face->blend;
+ num_axis = 0; /* make compiler happy */
+
+ for ( n = 0; n < (FT_UInt)num_designs; n++ )
+ {
+ T1_Token axis_tokens[ T1_MAX_MM_DESIGNS ];
+ T1_Token* token;
+ FT_Int axis, n_axis;
+
+
+ /* read axis/coordinates tokens */
+ token = design_tokens + n;
+ parser->root.cursor = token->start - 1;
+ parser->root.limit = token->limit + 1;
+ T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
+
+ if ( n == 0 )
+ {
+ num_axis = n_axis;
+ error = t1_allocate_blend( face, num_designs, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+ }
+ else if ( n_axis != num_axis )
+ {
+ FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* now, read each axis token into the design position */
+ for ( axis = 0; axis < n_axis; axis++ )
+ {
+ T1_Token* token2 = axis_tokens + axis;
+
+
+ parser->root.cursor = token2->start;
+ parser->root.limit = token2->limit;
+ blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
+ }
+ }
+
+ loader->parser.root.cursor = old_cursor;
+ loader->parser.root.limit = old_limit;
+ }
+
+ Exit:
+ loader->parser.root.error = error;
+ }
+
+
+ static
+ void parse_blend_design_map( T1_Face face,
+ T1_Loader* loader )
+ {
+ FT_Error error = 0;
+ T1_ParserRec* parser = &loader->parser;
+ T1_Blend* blend;
+ T1_Token axis_tokens[ T1_MAX_MM_AXIS ];
+ FT_Int n, num_axis;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+ FT_Memory memory = face->root.memory;
+
+
+ T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
+ if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
+ num_axis ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ old_cursor = parser->root.cursor;
+ old_limit = parser->root.limit;
+
+ error = t1_allocate_blend( face, 0, num_axis );
+ if ( error )
+ goto Exit;
+ blend = face->blend;
+
+ /* now, read each axis design map */
+ for ( n = 0; n < num_axis; n++ )
+ {
+ T1_DesignMap* map = blend->design_map + n;
+ T1_Token* token;
+ FT_Int p, num_points;
+
+
+ token = axis_tokens + n;
+ parser->root.cursor = token->start;
+ parser->root.limit = token->limit;
+
+ /* count the number of map points */
+ {
+ FT_Byte* ptr = token->start;
+ FT_Byte* limit = token->limit;
+
+
+ num_points = 0;
+ for ( ; ptr < limit; ptr++ )
+ if ( ptr[0] == '[' )
+ num_points++;
+ }
+ if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
+ {
+ FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ /* allocate design map data */
+ if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
+ goto Exit;
+ map->blend_points = map->design_points + num_points;
+ map->num_points = (FT_Byte)num_points;
+
+ for ( p = 0; p < num_points; p++ )
+ {
+ map->design_points[p] = T1_ToInt( parser );
+ map->blend_points [p] = T1_ToFixed( parser, 0 );
+ }
+ }
+
+ parser->root.cursor = old_cursor;
+ parser->root.limit = old_limit;
+
+ Exit:
+ parser->root.error = error;
+ }
+
+
+ static
+ void parse_weight_vector( T1_Face face,
+ T1_Loader* loader )
+ {
+ FT_Error error = 0;
+ T1_ParserRec* parser = &loader->parser;
+ T1_Blend* blend = face->blend;
+ T1_Token master;
+ FT_UInt n;
+ FT_Byte* old_cursor;
+ FT_Byte* old_limit;
+
+
+ if ( !blend || blend->num_designs == 0 )
+ {
+ FT_ERROR(( "parse_weight_vector: too early!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ T1_ToToken( parser, &master );
+ if ( master.type != t1_token_array )
+ {
+ FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ old_cursor = parser->root.cursor;
+ old_limit = parser->root.limit;
+
+ parser->root.cursor = master.start;
+ parser->root.limit = master.limit;
+
+ for ( n = 0; n < blend->num_designs; n++ )
+ {
+ blend->default_weight_vector[n] =
+ blend->weight_vector[n] = T1_ToFixed( parser, 0 );
+ }
+
+ parser->root.cursor = old_cursor;
+ parser->root.limit = old_limit;
+
+ Exit:
+ parser->root.error = error;
+ }
+
+
+ /* the keyword `/shareddict' appears in some multiple master fonts */
+ /* with a lot of Postscript garbage behind it (that's completely out */
+ /* of spec!); we detect it and terminate the parsing */
+ /* */
+ static
+ void parse_shared_dict( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+
+ FT_UNUSED( face );
+
+
+ parser->root.cursor = parser->root.limit;
+ parser->root.error = 0;
+ }
+
+#endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** TYPE 1 SYMBOL PARSING *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* First of all, define the token field static variables. This is a set */
+ /* of T1_Field variables used later. */
+ /* */
+ /*************************************************************************/
+
+
+ static
+ FT_Error t1_load_keyword( T1_Face face,
+ T1_Loader* loader,
+ T1_Field* field )
+ {
+ FT_Error error;
+ void* dummy_object;
+ void** objects;
+ FT_UInt max_objects;
+ T1_Blend* blend = face->blend;
+
+
+ /* if the keyword has a dedicated callback, call it */
+ if ( field->type == t1_field_callback )
+ {
+ field->reader( (FT_Face)face, loader );
+ error = loader->parser.root.error;
+ goto Exit;
+ }
+
+ /* now, the keyword is either a simple field, or a table of fields; */
+ /* we are now going to take care of it */
+ switch ( field->location )
+ {
+ case t1_field_font_info:
+ dummy_object = &face->type1.font_info;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->font_infos;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ case t1_field_private:
+ dummy_object = &face->type1.private_dict;
+ objects = &dummy_object;
+ max_objects = 0;
+
+ if ( blend )
+ {
+ objects = (void**)blend->privates;
+ max_objects = blend->num_designs;
+ }
+ break;
+
+ default:
+ dummy_object = &face->type1;
+ objects = &dummy_object;
+ max_objects = 0;
+ }
+
+ if ( field->type == t1_field_integer_array ||
+ field->type == t1_field_fixed_array )
+ error = T1_Load_Field_Table( &loader->parser, field,
+ objects, max_objects, 0 );
+ else
+ error = T1_Load_Field( &loader->parser, field,
+ objects, max_objects, 0 );
+
+ Exit:
+ return error;
+ }
+
+
+ static
+ int is_space( FT_Byte c )
+ {
+ return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
+ }
+
+
+ static
+ int is_alpha( FT_Byte c )
+ {
+ return ( isalnum( c ) || c == '.' || c == '_' );
+ }
+
+
+
+ static
+ int read_binary_data( T1_ParserRec* parser,
+ FT_Int* size,
+ FT_Byte** base )
+ {
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+
+
+ /* the binary data has the following format */
+ /* */
+ /* `size' [white*] RD white ....... ND */
+ /* */
+
+ T1_Skip_Spaces( parser );
+ cur = parser->root.cursor;
+
+ if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
+ {
+ *size = T1_ToInt( parser );
+
+ T1_Skip_Spaces( parser );
+ T1_Skip_Alpha ( parser ); /* `RD' or `-|' or something else */
+
+ /* there is only one whitespace char after the */
+ /* `RD' or `-|' token */
+ *base = parser->root.cursor + 1;
+
+ parser->root.cursor += *size + 1;
+ return 1;
+ }
+
+ FT_ERROR(( "read_binary_data: invalid size field\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return 0;
+ }
+
+
+ /* we will now define the routines used to handle */
+ /* the `/Encoding', `/Subrs', and `/CharStrings' */
+ /* dictionaries */
+
+ static
+ void parse_font_name( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ FT_Error error;
+ FT_Memory memory = parser->root.memory;
+ FT_Int len;
+ FT_Byte* cur;
+ FT_Byte* cur2;
+ FT_Byte* limit;
+
+
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+ limit = parser->root.limit;
+
+ if ( cur >= limit - 1 || *cur != '/' )
+ return;
+
+ cur++;
+ cur2 = cur;
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur;
+ if ( len > 0 )
+ {
+ if ( ALLOC( face->type1.font_name, len + 1 ) )
+ {
+ parser->root.error = error;
+ return;
+ }
+
+ MEM_Copy( face->type1.font_name, cur, len );
+ face->type1.font_name[len] = '\0';
+ }
+ parser->root.cursor = cur2;
+ }
+
+
+ static
+ void parse_font_bbox( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ FT_Short temp[4];
+ FT_BBox* bbox = &face->type1.font_bbox;
+
+
+ (void)T1_ToCoordArray( parser, 4, temp );
+ bbox->xMin = temp[0];
+ bbox->yMin = temp[1];
+ bbox->xMax = temp[2];
+ bbox->yMax = temp[3];
+ }
+
+
+ static
+ void parse_font_matrix( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ FT_Matrix* matrix = &face->type1.font_matrix;
+ FT_Vector* offset = &face->type1.font_offset;
+ FT_Fixed temp[6];
+
+
+ if ( matrix->xx || matrix->yx )
+ /* with synthetic fonts, it's possible we get here twice */
+ return;
+
+ (void)T1_ToFixedArray( parser, 6, temp, 3 );
+
+ /* we need to scale the values by 1.0/temp[3] */
+ if ( temp[3] != 0x10000L )
+ {
+ temp[0] = FT_DivFix( temp[0], temp[3] );
+ temp[1] = FT_DivFix( temp[1], temp[3] );
+ temp[2] = FT_DivFix( temp[2], temp[3] );
+ temp[4] = FT_DivFix( temp[4], temp[3] );
+ temp[5] = FT_DivFix( temp[5], temp[3] );
+ temp[3] = 0x10000L;
+ }
+
+ matrix->xx = temp[0];
+ matrix->yx = temp[1];
+ matrix->xy = temp[2];
+ matrix->yy = temp[3];
+
+ /* note that the offsets must be expressed in integer font units */
+ offset->x = temp[4] >> 16;
+ offset->y = temp[5] >> 16;
+ }
+
+
+ static
+ void parse_encoding( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ FT_Byte* cur = parser->root.cursor;
+ FT_Byte* limit = parser->root.limit;
+
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+
+
+ /* skip whitespace */
+ while ( is_space( *cur ) )
+ {
+ cur++;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "parse_encoding: out of bounds!\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ return;
+ }
+ }
+
+ /* if we have a number, then the encoding is an array, */
+ /* and we must load it now */
+ if ( (FT_Byte)( *cur - '0' ) < 10 )
+ {
+ T1_Encoding* encode = &face->type1.encoding;
+ FT_Int count, n;
+ PS_Table* char_table = &loader->encoding_table;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+
+
+ /* read the number of entries in the encoding, should be 256 */
+ count = T1_ToInt( parser );
+ if ( parser->root.error )
+ return;
+
+ /* we use a T1_Table to store our charnames */
+ encode->num_chars = count;
+ if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ||
+ ALLOC_ARRAY( encode->char_name, count, FT_String* ) ||
+ ( error = psaux->ps_table_funcs->init(
+ char_table, count, memory ) ) != 0 )
+ {
+ parser->root.error = error;
+ return;
+ }
+
+ /* We need to `zero' out encoding_table.elements */
+ for ( n = 0; n < count; n++ )
+ {
+ char* notdef = ".notdef";
+
+
+ T1_Add_Table( char_table, n, notdef, 8 );
+ }
+
+ /* Now, we will need to read a record of the form */
+ /* ... charcode /charname ... for each entry in our table */
+ /* */
+ /* We simply look for a number followed by an immediate */
+ /* name. Note that this ignores correctly the sequence */
+ /* that is often seen in type1 fonts: */
+ /* */
+ /* 0 1 255 { 1 index exch /.notdef put } for dup */
+ /* */
+ /* used to clean the encoding array before anything else. */
+ /* */
+ /* We stop when we encounter a `def'. */
+
+ cur = parser->root.cursor;
+ limit = parser->root.limit;
+ n = 0;
+
+ for ( ; cur < limit; )
+ {
+ FT_Byte c;
+
+
+ c = *cur;
+
+ /* we stop when we encounter a `def' */
+ if ( c == 'd' && cur + 3 < limit )
+ {
+ if ( cur[1] == 'e' &&
+ cur[2] == 'f' &&
+ is_space(cur[-1]) &&
+ is_space(cur[3]) )
+ {
+ FT_TRACE6(( "encoding end\n" ));
+ break;
+ }
+ }
+
+ /* otherwise, we must find a number before anything else */
+ if ( (FT_Byte)( c - '0' ) < 10 )
+ {
+ FT_Int charcode;
+
+
+ parser->root.cursor = cur;
+ charcode = T1_ToInt( parser );
+ cur = parser->root.cursor;
+
+ /* skip whitespace */
+ while ( cur < limit && is_space( *cur ) )
+ cur++;
+
+ if ( cur < limit && *cur == '/' )
+ {
+ /* bingo, we have an immediate name -- it must be a */
+ /* character name */
+ FT_Byte* cur2 = cur + 1;
+ FT_Int len;
+
+
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur - 1;
+
+ parser->root.error = T1_Add_Table( char_table, charcode,
+ cur + 1, len + 1 );
+ char_table->elements[charcode][len] = '\0';
+ if ( parser->root.error )
+ return;
+
+ cur = cur2;
+ }
+ }
+ else
+ cur++;
+ }
+
+ face->type1.encoding_type = t1_encoding_array;
+ parser->root.cursor = cur;
+ }
+ /* Otherwise, we should have either `StandardEncoding' or */
+ /* `ExpertEncoding' */
+ else
+ {
+ if ( cur + 17 < limit &&
+ strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
+ face->type1.encoding_type = t1_encoding_standard;
+
+ else if ( cur + 15 < limit &&
+ strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
+ face->type1.encoding_type = t1_encoding_expert;
+
+ else
+ {
+ FT_ERROR(( "parse_encoding: invalid token!\n" ));
+ parser->root.error = T1_Err_Invalid_File_Format;
+ }
+ }
+ }
+
+
+ static
+ void parse_subrs( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ PS_Table* table = &loader->subrs;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+ FT_Int n;
+
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+
+
+ loader->num_subrs = T1_ToInt( parser );
+ if ( parser->root.error )
+ return;
+
+ /* position the parser right before the `dup' of the first subr */
+ T1_Skip_Spaces( parser );
+ T1_Skip_Alpha( parser ); /* `array' */
+ T1_Skip_Spaces( parser );
+
+ /* initialize subrs array */
+ error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
+ if ( error )
+ goto Fail;
+
+ /* the format is simple: */
+ /* */
+ /* `index' + binary data */
+ /* */
+
+ for ( n = 0; n < loader->num_subrs; n++ )
+ {
+ FT_Int index, size;
+ FT_Byte* base;
+
+
+ /* If the next token isn't `dup', we are also done. This */
+ /* happens when there are `holes' in the Subrs array. */
+ if ( strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
+ break;
+
+ index = T1_ToInt( parser );
+
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ /* The binary string is followed by one token, e.g. `NP' */
+ /* (bound to `noaccess put') or by two separate tokens: */
+ /* `noaccess' & `put'. We position the parser right */
+ /* before the next `dup', if any. */
+ T1_Skip_Spaces( parser );
+ T1_Skip_Alpha( parser ); /* `NP' or `I' or `noaccess' */
+ T1_Skip_Spaces( parser );
+
+ if ( strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
+ {
+ T1_Skip_Alpha( parser ); /* skip `put' */
+ T1_Skip_Spaces( parser );
+ }
+
+ /* some fonts use a value of -1 for lenIV to indicate that */
+ /* the charstrings are unencoded */
+ /* */
+ /* thanks to Tom Kacvinsky for pointing this out */
+ /* */
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ T1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = T1_Add_Table( table, index, base, size );
+ if ( error )
+ goto Fail;
+ }
+ return;
+
+ Fail:
+ parser->root.error = error;
+ }
+
+
+ static
+ void parse_charstrings( T1_Face face,
+ T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+ PS_Table* code_table = &loader->charstrings;
+ PS_Table* name_table = &loader->glyph_names;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error;
+
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+
+ FT_Byte* cur;
+ FT_Byte* limit = parser->root.limit;
+ FT_Int n;
+ FT_UInt notdef_index = 0;
+ FT_Byte notdef_found = 0;
+
+
+ if ( loader->num_glyphs )
+ /* with synthetic fonts, it's possible we get here twice */
+ return;
+
+ loader->num_glyphs = T1_ToInt( parser );
+ if ( parser->root.error )
+ return;
+
+ /* initialize tables, adding space for `swap' at table end */
+ error = psaux->ps_table_funcs->init( code_table,
+ loader->num_glyphs + 1,
+ memory );
+ if ( error )
+ goto Fail;
+
+ error = psaux->ps_table_funcs->init( name_table,
+ loader->num_glyphs + 1,
+ memory );
+ if ( error )
+ goto Fail;
+
+ n = 0;
+ for (;;)
+ {
+ FT_Int size;
+ FT_Byte* base;
+
+
+ /* the format is simple: */
+ /* `/glyphname' + binary data */
+ /* */
+ /* note that we stop when we find a `def' */
+ /* */
+ T1_Skip_Spaces( parser );
+
+ cur = parser->root.cursor;
+ if ( cur >= limit )
+ break;
+
+ /* we stop when we find a `def' or `end' keyword */
+ if ( *cur == 'd' &&
+ cur + 3 < limit &&
+ cur[1] == 'e' &&
+ cur[2] == 'f' )
+ break;
+
+ if ( *cur == 'e' &&
+ cur + 3 < limit &&
+ cur[1] == 'n' &&
+ cur[2] == 'd' )
+ break;
+
+ if ( *cur != '/' )
+ T1_Skip_Alpha( parser );
+ else
+ {
+ FT_Byte* cur2 = cur + 1;
+ FT_Int len;
+
+
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+ len = cur2 - cur - 1;
+
+ error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
+ if ( error )
+ goto Fail;
+
+ /* add a trailing zero to the name table */
+ name_table->elements[n][len] = '\0';
+
+ /* record index of /.notdef */
+ if ( strcmp( (const char*)".notdef",
+ (const char*)(name_table->elements[n]) ) == 0 )
+ {
+ notdef_index = n;
+ notdef_found = 1;
+ }
+
+ parser->root.cursor = cur2;
+ if ( !read_binary_data( parser, &size, &base ) )
+ return;
+
+ if ( face->type1.private_dict.lenIV >= 0 )
+ {
+ T1_Decrypt( base, size, 4330 );
+ size -= face->type1.private_dict.lenIV;
+ base += face->type1.private_dict.lenIV;
+ }
+
+ error = T1_Add_Table( code_table, n, base, size );
+ if ( error )
+ goto Fail;
+
+ n++;
+ if ( n >= loader->num_glyphs )
+ break;
+ }
+ }
+
+ loader->num_glyphs = n;
+
+ /* if /.notdef is found but does not occupy index 0, do our magic. */
+ if ( strcmp( (const char*)".notdef",
+ (const char*)name_table->elements[0] ) &&
+ notdef_found )
+ {
+
+ /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
+ /* name/code to end of table. Then place notdef_index name/code into */
+ /* index 0. Then take end of table name/code and place it into index */
+ /* notdef_index. */
+
+ error = T1_Add_Table( name_table, n,
+ name_table->elements[0],
+ name_table->lengths [0] );
+ if ( error )
+ goto Fail;
+ error = T1_Add_Table( code_table, n,
+ code_table->elements[0],
+ code_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, 0,
+ name_table->elements[notdef_index],
+ name_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, 0,
+ code_table->elements[notdef_index],
+ code_table->lengths [notdef_index] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, notdef_index,
+ name_table->elements[n],
+ name_table->lengths [n] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, notdef_index,
+ code_table->elements[n],
+ code_table->lengths [n] );
+ if ( error )
+ goto Fail;
+
+ }
+ else if ( !notdef_found )
+ {
+
+ /* notdef_index is already 0, or /.notdef is undefined in */
+ /* charstrings dictionary. Worry about /.notdef undefined. */
+ /* we take index 0 and add it to the end of the table(s) */
+ /* and add our own /.notdef glyph to index 0. */
+
+ /* 0 333 hsbw endchar */
+ FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
+ char* notdef_name = ".notdef";
+
+
+ error = T1_Add_Table( name_table, n,
+ name_table->elements[0],
+ name_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, n,
+ code_table->elements[0],
+ code_table->lengths [0] );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( name_table, 0, notdef_name, 8 );
+ if ( error )
+ goto Fail;
+
+ error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
+
+ if ( error )
+ goto Fail;
+
+ /* we added a glyph. */
+ loader->num_glyphs = n + 1;
+
+ }
+
+ return;
+
+ Fail:
+ parser->root.error = error;
+ }
+
+
+ static
+ const T1_Field t1_keywords[] =
+ {
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1tokens.h"
+
+#else
+
+#include <type1/t1tokens.h>
+
+#endif
+
+ /* now add the special functions... */
+ T1_FIELD_CALLBACK( "FontName", parse_font_name )
+ T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
+ T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
+ T1_FIELD_CALLBACK( "Encoding", parse_encoding )
+ T1_FIELD_CALLBACK( "Subrs", parse_subrs )
+ T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
+ T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
+ T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
+ T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
+ T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
+#endif
+
+ { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
+ };
+
+
+ static
+ FT_Error parse_dict( T1_Face face,
+ T1_Loader* loader,
+ FT_Byte* base,
+ FT_Long size )
+ {
+ T1_ParserRec* parser = &loader->parser;
+
+
+ parser->root.cursor = base;
+ parser->root.limit = base + size;
+ parser->root.error = 0;
+
+ {
+ FT_Byte* cur = base;
+ FT_Byte* limit = cur + size;
+
+
+ for ( ; cur < limit; cur++ )
+ {
+ /* look for `FontDirectory', which causes problems on some fonts */
+ if ( *cur == 'F' && cur + 25 < limit &&
+ strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
+ {
+ FT_Byte* cur2;
+
+
+ /* skip the `FontDirectory' keyword */
+ cur += 13;
+ cur2 = cur;
+
+ /* lookup the `known' keyword */
+ while ( cur < limit && *cur != 'k' &&
+ strncmp( (char*)cur, "known", 5 ) )
+ cur++;
+
+ if ( cur < limit )
+ {
+ T1_Token token;
+
+
+ /* skip the `known' keyword and the token following it */
+ cur += 5;
+ loader->parser.root.cursor = cur;
+ T1_ToToken( &loader->parser, &token );
+
+ /* if the last token was an array, skip it! */
+ if ( token.type == t1_token_array )
+ cur2 = parser->root.cursor;
+ }
+ cur = cur2;
+ }
+ /* look for immediates */
+ else if ( *cur == '/' && cur + 2 < limit )
+ {
+ FT_Byte* cur2;
+ FT_Int len;
+
+
+ cur++;
+ cur2 = cur;
+ while ( cur2 < limit && is_alpha( *cur2 ) )
+ cur2++;
+
+ len = cur2 - cur;
+ if ( len > 0 && len < 22 )
+ {
+ if ( !loader->fontdata )
+ {
+ if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
+ loader->fontdata = 1;
+ }
+ else
+ {
+ /* now, compare the immediate name to the keyword table */
+ T1_Field* keyword = (T1_Field*)t1_keywords;
+
+
+ for (;;)
+ {
+ FT_Byte* name;
+
+
+ name = (FT_Byte*)keyword->ident;
+ if ( !name )
+ break;
+
+ if ( cur[0] == name[0] &&
+ len == (FT_Int)strlen( (const char*)name ) )
+ {
+ FT_Int n;
+
+
+ for ( n = 1; n < len; n++ )
+ if ( cur[n] != name[n] )
+ break;
+
+ if ( n >= len )
+ {
+ /* we found it -- run the parsing callback! */
+ parser->root.cursor = cur2;
+ T1_Skip_Spaces( parser );
+ parser->root.error = t1_load_keyword( face,
+ loader,
+ keyword );
+ if ( parser->root.error )
+ return parser->root.error;
+
+ cur = parser->root.cursor;
+ break;
+ }
+ }
+ keyword++;
+ }
+ }
+ }
+ }
+ }
+ }
+ return parser->root.error;
+ }
+
+
+ static
+ void t1_init_loader( T1_Loader* loader,
+ T1_Face face )
+ {
+ FT_UNUSED( face );
+
+ MEM_Set( loader, 0, sizeof ( *loader ) );
+ loader->num_glyphs = 0;
+ loader->num_chars = 0;
+
+ /* initialize the tables -- simply set their `init' field to 0 */
+ loader->encoding_table.init = 0;
+ loader->charstrings.init = 0;
+ loader->glyph_names.init = 0;
+ loader->subrs.init = 0;
+ loader->fontdata = 0;
+ }
+
+
+ static
+ void t1_done_loader( T1_Loader* loader )
+ {
+ T1_ParserRec* parser = &loader->parser;
+
+
+ /* finalize tables */
+ T1_Release_Table( &loader->encoding_table );
+ T1_Release_Table( &loader->charstrings );
+ T1_Release_Table( &loader->glyph_names );
+ T1_Release_Table( &loader->subrs );
+
+ /* finalize parser */
+ T1_Done_Parser( parser );
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Open_Face( T1_Face face )
+ {
+ T1_Loader loader;
+ T1_ParserRec* parser;
+ T1_Font* type1 = &face->type1;
+ FT_Error error;
+
+ PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
+
+
+ t1_init_loader( &loader, face );
+
+ /* default lenIV */
+ type1->private_dict.lenIV = 4;
+
+ parser = &loader.parser;
+ error = T1_New_Parser( parser,
+ face->root.stream,
+ face->root.memory,
+ psaux );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
+ if ( error )
+ goto Exit;
+
+ error = T1_Get_Private_Dict( parser );
+ if ( error )
+ goto Exit;
+
+ error = parse_dict( face, &loader, parser->private_dict,
+ parser->private_len );
+ if ( error )
+ goto Exit;
+
+ /* now, propagate the subrs, charstrings, and glyphnames tables */
+ /* to the Type1 data */
+ type1->num_glyphs = loader.num_glyphs;
+
+ if ( !loader.subrs.init )
+ {
+ FT_ERROR(( "T1_Open_Face: no subrs array in face!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ if ( !loader.charstrings.init )
+ {
+ FT_ERROR(( "T1_Open_Face: no charstrings array in face!\n" ));
+ error = T1_Err_Invalid_File_Format;
+ }
+
+ loader.subrs.init = 0;
+ type1->num_subrs = loader.num_subrs;
+ type1->subrs_block = loader.subrs.block;
+ type1->subrs = loader.subrs.elements;
+ type1->subrs_len = loader.subrs.lengths;
+
+ loader.charstrings.init = 0;
+ type1->charstrings_block = loader.charstrings.block;
+ type1->charstrings = loader.charstrings.elements;
+ type1->charstrings_len = loader.charstrings.lengths;
+
+ /* we copy the glyph names `block' and `elements' fields; */
+ /* the `lengths' field must be released later */
+ type1->glyph_names_block = loader.glyph_names.block;
+ type1->glyph_names = (FT_String**)loader.glyph_names.elements;
+ loader.glyph_names.block = 0;
+ loader.glyph_names.elements = 0;
+
+ /* we must now build type1.encoding when we have a custom */
+ /* array.. */
+ if ( type1->encoding_type == t1_encoding_array )
+ {
+ FT_Int charcode, index, min_char, max_char;
+ FT_Byte* char_name;
+ FT_Byte* glyph_name;
+
+
+ /* OK, we do the following: for each element in the encoding */
+ /* table, look up the index of the glyph having the same name */
+ /* the index is then stored in type1.encoding.char_index, and */
+ /* a the name to type1.encoding.char_name */
+
+ min_char = +32000;
+ max_char = -32000;
+
+ charcode = 0;
+ for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
+ {
+ type1->encoding.char_index[charcode] = 0;
+ type1->encoding.char_name [charcode] = (char *)".notdef";
+
+ char_name = loader.encoding_table.elements[charcode];
+ if ( char_name )
+ for ( index = 0; index < type1->num_glyphs; index++ )
+ {
+ glyph_name = (FT_Byte*)type1->glyph_names[index];
+ if ( strcmp( (const char*)char_name,
+ (const char*)glyph_name ) == 0 )
+ {
+ type1->encoding.char_index[charcode] = index;
+ type1->encoding.char_name [charcode] = (char*)glyph_name;
+
+ /* Change min/max encoded char only if glyph name is */
+ /* not /.notdef */
+ if ( strcmp( (const char*)".notdef",
+ (const char*)glyph_name ) != 0 )
+ {
+ if (charcode < min_char) min_char = charcode;
+ if (charcode > max_char) max_char = charcode;
+ }
+ break;
+ }
+ }
+ }
+ type1->encoding.code_first = min_char;
+ type1->encoding.code_last = max_char;
+ type1->encoding.num_chars = loader.num_chars;
+ }
+
+ Exit:
+ t1_done_loader( &loader );
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1load.h
@@ -1,0 +1,93 @@
+/***************************************************************************/
+/* */
+/* t1load.h */
+/* */
+/* Type 1 font 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. */
+/* */
+/***************************************************************************/
+
+
+#ifndef T1LOAD_H
+#define T1LOAD_H
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/psaux.h>
+#include <freetype/ftmm.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ typedef struct T1_Loader_
+ {
+ T1_ParserRec parser; /* parser used to read the stream */
+
+ FT_Int num_chars; /* number of characters in encoding */
+ PS_Table encoding_table; /* PS_Table used to store the */
+ /* encoding character names */
+
+ FT_Int num_glyphs;
+ PS_Table glyph_names;
+ PS_Table charstrings;
+
+ FT_Int num_subrs;
+ PS_Table subrs;
+ FT_Bool fontdata;
+
+ } T1_Loader;
+
+
+ LOCAL_DEF
+ FT_Error T1_Open_Face( T1_Face face );
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+
+ LOCAL_DEF
+ FT_Error T1_Get_Multi_Master( T1_Face face,
+ FT_Multi_Master* master );
+
+ LOCAL_DEF
+ FT_Error T1_Set_MM_Blend( T1_Face face,
+ FT_UInt num_coords,
+ FT_Fixed* coords );
+
+ LOCAL_DEF
+ FT_Error T1_Set_MM_Design( T1_Face face,
+ FT_UInt num_coords,
+ FT_Long* coords );
+
+ LOCAL_DEF
+ void T1_Done_Blend( T1_Face face );
+
+#endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1LOAD_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1objs.c
@@ -1,0 +1,406 @@
+/***************************************************************************/
+/* */
+/* t1objs.c */
+/* */
+/* Type 1 objects manager (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. */
+/* */
+/***************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftstream.h>
+
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1gload.h"
+#include "t1load.h"
+#include "t1afm.h"
+
+#else
+
+#include <type1/t1gload.h>
+#include <type1/t1load.h>
+#include <type1/t1afm.h>
+
+#endif
+
+
+#include <freetype/internal/psnames.h>
+#include <freetype/internal/psaux.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_t1objs
+
+
+ /*************************************************************************/
+ /* */
+ /* FACE FUNCTIONS */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Face */
+ /* */
+ /* <Description> */
+ /* The face object destructor. */
+ /* */
+ /* <Input> */
+ /* face :: A typeless pointer to the face object to destroy. */
+ /* */
+ LOCAL_FUNC
+ void T1_Done_Face( T1_Face face )
+ {
+ FT_Memory memory;
+ T1_Font* type1 = &face->type1;
+
+
+ if ( face )
+ {
+ memory = face->root.memory;
+
+#ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
+ /* release multiple masters information */
+ T1_Done_Blend( face );
+ face->blend = 0;
+#endif
+
+ /* release font info strings */
+ {
+ T1_FontInfo* info = &type1->font_info;
+
+
+ FREE( info->version );
+ FREE( info->notice );
+ FREE( info->full_name );
+ FREE( info->family_name );
+ FREE( info->weight );
+ }
+
+ /* release top dictionary */
+ FREE( type1->charstrings_len );
+ FREE( type1->charstrings );
+ FREE( type1->glyph_names );
+
+ FREE( type1->subrs );
+ FREE( type1->subrs_len );
+
+ FREE( type1->subrs_block );
+ FREE( type1->charstrings_block );
+ FREE( type1->glyph_names_block );
+
+ FREE( type1->encoding.char_index );
+ FREE( type1->font_name );
+
+#ifndef T1_CONFIG_OPTION_NO_AFM
+ /* release afm data if present */
+ if ( face->afm_data )
+ T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
+#endif
+
+ /* release unicode map, if any */
+ FREE( face->unicode_map.maps );
+ face->unicode_map.num_maps = 0;
+
+ face->root.family_name = 0;
+ face->root.style_name = 0;
+ }
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Face */
+ /* */
+ /* <Description> */
+ /* The face object constructor. */
+ /* */
+ /* <Input> */
+ /* stream :: input stream where to load font data. */
+ /* */
+ /* face_index :: The index of the font face in the resource. */
+ /* */
+ /* num_params :: Number of additional generic parameters. Ignored. */
+ /* */
+ /* params :: Additional generic parameters. Ignored. */
+ /* */
+ /* <InOut> */
+ /* face :: The face record to build. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params )
+ {
+ FT_Error error;
+ PSNames_Interface* psnames;
+ PSAux_Interface* psaux;
+
+ FT_UNUSED( num_params );
+ FT_UNUSED( params );
+ FT_UNUSED( face_index );
+ FT_UNUSED( stream );
+
+
+ face->root.num_faces = 1;
+
+ psnames = (PSNames_Interface*)face->psnames;
+ if ( !psnames )
+ {
+ psnames = (PSNames_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
+
+ face->psnames = psnames;
+ }
+
+ psaux = (PSAux_Interface*)face->psaux;
+ if ( !psaux )
+ {
+ psaux = (PSAux_Interface*)
+ FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
+
+ face->psaux = psaux;
+ }
+
+ /* open the tokenizer, this will also check the font format */
+ error = T1_Open_Face( face );
+ if ( error )
+ goto Exit;
+
+ /* if we just wanted to check the format, leave successfully now */
+ if ( face_index < 0 )
+ goto Exit;
+
+ /* check the face index */
+ if ( face_index != 0 )
+ {
+ FT_ERROR(( "T1_Init_Face: invalid face index\n" ));
+ error = T1_Err_Invalid_Argument;
+ goto Exit;
+ }
+
+ /* Now, load the font program into the face object */
+
+ /* Init the face object fields */
+ /* Now set up root face fields */
+ {
+ FT_Face root = (FT_Face)&face->root;
+
+
+ root->num_glyphs = face->type1.num_glyphs;
+ root->num_charmaps = 1;
+
+ root->face_index = face_index;
+ root->face_flags = FT_FACE_FLAG_SCALABLE;
+
+ root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
+
+ root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
+
+ if ( face->type1.font_info.is_fixed_pitch )
+ root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
+
+ if ( face->blend )
+ root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
+
+ /* XXX: TODO -- add kerning with .afm support */
+
+ /* get style name -- be careful, some broken fonts only */
+ /* have a `/FontName' dictionary entry! */
+ root->family_name = face->type1.font_info.family_name;
+ if ( root->family_name )
+ {
+ char* full = face->type1.font_info.full_name;
+ char* family = root->family_name;
+
+
+ while ( *family && *full == *family )
+ {
+ family++;
+ full++;
+ }
+
+ root->style_name = ( *full == ' ' ? full + 1
+ : (char *)"Regular" );
+ }
+ else
+ {
+ /* do we have a `/FontName'? */
+ if ( face->type1.font_name )
+ {
+ root->family_name = face->type1.font_name;
+ root->style_name = (char *)"Regular";
+ }
+ }
+
+ /* no embedded bitmap support */
+ root->num_fixed_sizes = 0;
+ root->available_sizes = 0;
+
+ root->bbox = face->type1.font_bbox;
+ root->units_per_EM = 1000;
+ root->ascender = (FT_Short)face->type1.font_bbox.yMax;
+ root->descender = (FT_Short)face->type1.font_bbox.yMin;
+ root->height = ( ( root->ascender + root->descender ) * 12 ) / 10;
+
+ /* now compute the maximum advance width */
+
+ root->max_advance_width = face->type1.private_dict.standard_width[0];
+
+ /* compute max advance width for proportional fonts */
+ if ( !face->type1.font_info.is_fixed_pitch )
+ {
+ FT_Int max_advance;
+
+
+ error = T1_Compute_Max_Advance( face, &max_advance );
+
+ /* in case of error, keep the standard width */
+ if ( !error )
+ root->max_advance_width = max_advance;
+ else
+ error = 0; /* clear error */
+ }
+
+ root->max_advance_height = root->height;
+
+ root->underline_position = face->type1.font_info.underline_position;
+ root->underline_thickness = face->type1.font_info.underline_thickness;
+
+ root->max_points = 0;
+ root->max_contours = 0;
+ }
+
+ /* charmap support -- synthetize unicode charmap if possible */
+ {
+ FT_Face root = &face->root;
+ FT_CharMap charmap = face->charmaprecs;
+
+
+ /* synthesize a Unicode charmap if there is support in the `PSNames' */
+ /* module */
+ if ( psnames )
+ {
+ if ( psnames->unicode_value )
+ {
+ error = psnames->build_unicodes(
+ root->memory,
+ face->type1.num_glyphs,
+ (const char**)face->type1.glyph_names,
+ &face->unicode_map );
+ if ( !error )
+ {
+ root->charmap = charmap;
+ charmap->face = (FT_Face)face;
+ charmap->encoding = ft_encoding_unicode;
+ charmap->platform_id = 3;
+ charmap->encoding_id = 1;
+ charmap++;
+ }
+
+ /* simply clear the error in case of failure (which really) */
+ /* means that out of memory or no unicode glyph names */
+ error = FT_Err_Ok;
+ }
+ }
+
+ /* now, support either the standard, expert, or custom encoding */
+ charmap->face = (FT_Face)face;
+ charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
+
+ switch ( face->type1.encoding_type )
+ {
+ case t1_encoding_standard:
+ charmap->encoding = ft_encoding_adobe_standard;
+ charmap->encoding_id = 0;
+ break;
+
+ case t1_encoding_expert:
+ charmap->encoding = ft_encoding_adobe_expert;
+ charmap->encoding_id = 1;
+ break;
+
+ default:
+ charmap->encoding = ft_encoding_adobe_custom;
+ charmap->encoding_id = 2;
+ break;
+ }
+
+ root->charmaps = face->charmaps;
+ root->num_charmaps = charmap - face->charmaprecs + 1;
+ face->charmaps[0] = &face->charmaprecs[0];
+ face->charmaps[1] = &face->charmaprecs[1];
+ }
+
+ Exit:
+ return error;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Init_Driver */
+ /* */
+ /* <Description> */
+ /* Initializes a given Type 1 driver object. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target driver object. */
+ /* */
+ /* <Return> */
+ /* FreeType error code. 0 means success. */
+ /* */
+ LOCAL_FUNC
+ FT_Error T1_Init_Driver( T1_Driver driver )
+ {
+ FT_UNUSED( driver );
+
+ return T1_Err_Ok;
+ }
+
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* T1_Done_Driver */
+ /* */
+ /* <Description> */
+ /* Finalizes a given Type 1 driver. */
+ /* */
+ /* <Input> */
+ /* driver :: A handle to the target Type 1 driver. */
+ /* */
+ LOCAL_DEF
+ void T1_Done_Driver( T1_Driver driver )
+ {
+ FT_UNUSED( driver );
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1objs.h
@@ -1,0 +1,161 @@
+/***************************************************************************/
+/* */
+/* t1objs.h */
+/* */
+/* Type 1 objects manager (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 T1OBJS_H
+#define T1OBJS_H
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/config/ftconfig.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/t1types.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+ /* The following structures must be defined by the hinter */
+ typedef struct T1_Size_Hints_ T1_Size_Hints;
+ typedef struct T1_Glyph_Hints_ T1_Glyph_Hints;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Driver */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 driver object. */
+ /* */
+ typedef struct T1_DriverRec_ *T1_Driver;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_Size */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 size object. */
+ /* */
+ typedef struct T1_SizeRec_* T1_Size;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlot */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 glyph slot object. */
+ /* */
+ typedef struct T1_GlyphSlotRec_* T1_GlyphSlot;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_CharMap */
+ /* */
+ /* <Description> */
+ /* A handle to a Type 1 character mapping object. */
+ /* */
+ /* <Note> */
+ /* The Type 1 format doesn't use a charmap but an encoding table. */
+ /* The driver is responsible for making up charmap objects */
+ /* corresponding to these tables. */
+ /* */
+ typedef struct T1_CharMapRec_* T1_CharMap;
+
+
+ /*************************************************************************/
+ /* */
+ /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
+ /* */
+ /*************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_SizeRec */
+ /* */
+ /* <Description> */
+ /* Type 1 size record. */
+ /* */
+ typedef struct T1_SizeRec_
+ {
+ FT_SizeRec root;
+ FT_Bool valid;
+ T1_Size_Hints* hints; /* defined in the hinter. This allows */
+ /* us to experiment with different */
+ /* hinting schemes without having to */
+ /* change `t1objs' each time. */
+ } T1_SizeRec;
+
+
+ /*************************************************************************/
+ /* */
+ /* <Type> */
+ /* T1_GlyphSlotRec */
+ /* */
+ /* <Description> */
+ /* Type 1 glyph slot record. */
+ /* */
+ typedef struct T1_GlyphSlotRec_
+ {
+ FT_GlyphSlotRec root;
+
+ FT_Bool hint;
+ FT_Bool scaled;
+
+ FT_Int max_points;
+ FT_Int max_contours;
+
+ FT_Fixed x_scale;
+ FT_Fixed y_scale;
+
+ T1_Glyph_Hints* hints; /* defined in the hinter */
+
+ } T1_GlyphSlotRec;
+
+
+ LOCAL_DEF
+ FT_Error T1_Init_Face( FT_Stream stream,
+ T1_Face face,
+ FT_Int face_index,
+ FT_Int num_params,
+ FT_Parameter* params );
+
+ LOCAL_DEF
+ void T1_Done_Face( T1_Face face );
+
+ LOCAL_DEF
+ FT_Error T1_Init_Driver( T1_Driver driver );
+
+ LOCAL_DEF
+ void T1_Done_Driver( T1_Driver driver );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* T1OBJS_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1parse.c
@@ -1,0 +1,487 @@
+/***************************************************************************/
+/* */
+/* t1parse.c */
+/* */
+/* Type 1 parser (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. */
+/* */
+/***************************************************************************/
+
+
+ /*************************************************************************/
+ /* */
+ /* The Type 1 parser is in charge of the following: */
+ /* */
+ /* - provide an implementation of a growing sequence of objects called */
+ /* a `T1_Table' (used to build various tables needed by the loader). */
+ /* */
+ /* - opening .pfb and .pfa files to extract their top-level and private */
+ /* dictionaries. */
+ /* */
+ /* - read numbers, arrays & strings from any dictionary. */
+ /* */
+ /* See `t1load.c' to see how data is loaded from the font file. */
+ /* */
+ /*************************************************************************/
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftcalc.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/t1errors.h>
+#include <freetype/internal/psaux.h>
+
+#ifdef FT_FLAT_COMPILE
+
+#include "t1parse.h"
+
+#else
+
+#include <type1/t1parse.h>
+
+#endif
+
+
+#include <string.h> /* for strncmp() */
+
+
+ /*************************************************************************/
+ /* */
+ /* 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_t1parse
+
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+ /***** *****/
+ /***** INPUT STREAM PARSER *****/
+ /***** *****/
+ /*************************************************************************/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
+#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
+
+#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
+
+
+ typedef struct PFB_Tag_
+ {
+ FT_UShort tag;
+ FT_Long size;
+
+ } PFB_Tag;
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE PFB_Tag
+
+
+ static
+ const FT_Frame_Field pfb_tag_fields[] =
+ {
+ FT_FRAME_START( 6 ),
+ FT_FRAME_USHORT ( tag ),
+ FT_FRAME_LONG_LE( size ),
+ FT_FRAME_END
+ };
+
+
+ static
+ FT_Error read_pfb_tag( FT_Stream stream,
+ FT_UShort* tag,
+ FT_Long* size )
+ {
+ FT_Error error;
+ PFB_Tag head;
+
+
+ *tag = 0;
+ *size = 0;
+ if ( !READ_Fields( pfb_tag_fields, &head ) )
+ {
+ if ( head.tag == 0x8001 || head.tag == 0x8002 )
+ {
+ *tag = head.tag;
+ *size = head.size;
+ }
+ }
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_New_Parser( T1_ParserRec* parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Interface* psaux )
+ {
+ FT_Error error;
+ FT_UShort tag;
+ FT_Long size;
+
+
+ psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
+
+ parser->stream = stream;
+ parser->base_len = 0;
+ parser->base_dict = 0;
+ parser->private_len = 0;
+ parser->private_dict = 0;
+ parser->in_pfb = 0;
+ parser->in_memory = 0;
+ parser->single_block = 0;
+
+ /******************************************************************/
+ /* */
+ /* Here a short summary of what is going on: */
+ /* */
+ /* When creating a new Type 1 parser, we try to locate and load */
+ /* the base dictionary if this is possible (i.e. for PFB */
+ /* files). Otherwise, we load the whole font into memory. */
+ /* */
+ /* When `loading' the base dictionary, we only setup pointers */
+ /* in the case of a memory-based stream. Otherwise, we */
+ /* allocate and load the base dictionary in it. */
+ /* */
+ /* parser->in_pfb is set if we are in a binary (".pfb") font. */
+ /* parser->in_memory is set if we have a memory stream. */
+ /* */
+
+ /* try to compute the size of the base dictionary; */
+ /* look for a Postscript binary file tag, i.e 0x8001 */
+ if ( FILE_Seek( 0L ) )
+ goto Exit;
+
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Exit;
+
+ if ( tag != 0x8001 )
+ {
+ /* assume that this is a PFA file for now; an error will */
+ /* be produced later when more things are checked */
+ if ( FILE_Seek( 0L ) )
+ goto Exit;
+ size = stream->size;
+ }
+ else
+ parser->in_pfb = 1;
+
+ /* now, try to load `size' bytes of the `base' dictionary we */
+ /* found previously */
+
+ /* if it is a memory-based resource, set up pointers */
+ if ( !stream->read )
+ {
+ parser->base_dict = (FT_Byte*)stream->base + stream->pos;
+ parser->base_len = size;
+ parser->in_memory = 1;
+
+ /* check that the `size' field is valid */
+ if ( FILE_Skip( size ) )
+ goto Exit;
+ }
+ else
+ {
+ /* read segment in memory */
+ if ( ALLOC( parser->base_dict, size ) ||
+ FILE_Read( parser->base_dict, size ) )
+ goto Exit;
+ parser->base_len = size;
+ }
+
+ /* Now check font format; we must see `%!PS-AdobeFont-1' */
+ /* or `%!FontType' */
+ {
+ if ( size <= 16 ||
+ ( strncmp( (const char*)parser->base_dict,
+ "%!PS-AdobeFont-1", 16 ) &&
+ strncmp( (const char*)parser->base_dict,
+ "%!FontType", 10 ) ) )
+ {
+ FT_TRACE2(( "[not a Type1 font]\n" ));
+ error = FT_Err_Unknown_File_Format;
+ }
+ else
+ {
+ parser->root.base = parser->base_dict;
+ parser->root.cursor = parser->base_dict;
+ parser->root.limit = parser->root.cursor + parser->base_len;
+ }
+ }
+
+ Exit:
+ if ( error && !parser->in_memory )
+ FREE( parser->base_dict );
+
+ return error;
+ }
+
+
+ LOCAL_FUNC
+ void T1_Done_Parser( T1_ParserRec* parser )
+ {
+ FT_Memory memory = parser->root.memory;
+
+
+ /* always free the private dictionary */
+ FREE( parser->private_dict );
+
+ /* free the base dictionary only when we have a disk stream */
+ if ( !parser->in_memory )
+ FREE( parser->base_dict );
+
+ parser->root.funcs.done( &parser->root );
+ }
+
+
+ /* return the value of an hexadecimal digit */
+ static
+ int hexa_value( char c )
+ {
+ unsigned int d;
+
+
+ d = (unsigned int)( c - '0' );
+ if ( d <= 9 )
+ return (int)d;
+
+ d = (unsigned int)( c - 'a' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ d = (unsigned int)( c - 'A' );
+ if ( d <= 5 )
+ return (int)( d + 10 );
+
+ return -1;
+ }
+
+
+ LOCAL_FUNC
+ void T1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed )
+ {
+ while ( length > 0 )
+ {
+ FT_Byte plain;
+
+
+ plain = ( *buffer ^ ( seed >> 8 ) );
+ seed = ( *buffer + seed ) * 52845 + 22719;
+ *buffer++ = plain;
+ length--;
+ }
+ }
+
+
+ LOCAL_FUNC
+ FT_Error T1_Get_Private_Dict( T1_ParserRec* parser )
+ {
+ FT_Stream stream = parser->stream;
+ FT_Memory memory = parser->root.memory;
+ FT_Error error = 0;
+ FT_Long size;
+
+
+ if ( parser->in_pfb )
+ {
+ /* in the case of the PFB format, the private dictionary can be */
+ /* made of several segments. We thus first read the number of */
+ /* segments to compute the total size of the private dictionary */
+ /* then re-read them into memory. */
+ FT_Long start_pos = FILE_Pos();
+ FT_UShort tag;
+
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error )
+ goto Fail;
+
+ if ( tag != 0x8002 )
+ break;
+
+ parser->private_len += size;
+
+ if ( FILE_Skip( size ) )
+ goto Fail;
+ }
+
+ /* Check that we have a private dictionary there */
+ /* and allocate private dictionary buffer */
+ if ( parser->private_len == 0 )
+ {
+ FT_ERROR(( "T1_Get_Private_Dict:" ));
+ FT_ERROR(( " invalid private dictionary section\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Fail;
+ }
+
+ if ( FILE_Seek( start_pos ) ||
+ ALLOC( parser->private_dict, parser->private_len ) )
+ goto Fail;
+
+ parser->private_len = 0;
+ for (;;)
+ {
+ error = read_pfb_tag( stream, &tag, &size );
+ if ( error || tag != 0x8002 )
+ {
+ error = FT_Err_Ok;
+ break;
+ }
+
+ if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
+ goto Fail;
+
+ parser->private_len += size;
+ }
+ }
+ else
+ {
+ /* we have already `loaded' the whole PFA font file into memory; */
+ /* if this is a memory resource, allocate a new block to hold */
+ /* the private dict. Otherwise, simply overwrite into the base */
+ /* dictionary block in the heap. */
+
+ /* first of all, look at the `eexec' keyword */
+ FT_Byte* cur = parser->base_dict;
+ FT_Byte* limit = cur + parser->base_len;
+ FT_Byte c;
+
+
+ for (;;)
+ {
+ c = cur[0];
+ if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
+ /* newline + 4 chars */
+ {
+ if ( cur[1] == 'e' && cur[2] == 'x' &&
+ cur[3] == 'e' && cur[4] == 'c' )
+ {
+ cur += 6; /* we skip the newling after the `eexec' */
+
+ /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
+ /* skip the extra \n if we find it */
+ if ( cur[0] == '\n' )
+ cur++;
+
+ break;
+ }
+ }
+ cur++;
+ if ( cur >= limit )
+ {
+ FT_ERROR(( "T1_Get_Private_Dict:" ));
+ FT_ERROR(( " could not find `eexec' keyword\n" ));
+ error = T1_Err_Invalid_File_Format;
+ goto Exit;
+ }
+ }
+
+ /* now determine where to write the _encrypted_ binary private */
+ /* dictionary. We overwrite the base dictionary for disk-based */
+ /* resources and allocate a new block otherwise */
+
+ size = parser->base_len - ( cur - parser->base_dict);
+
+ if ( parser->in_memory )
+ {
+ /* note that we allocate one more byte to put a terminating `0' */
+ if ( ALLOC( parser->private_dict, size + 1 ) )
+ goto Fail;
+ parser->private_len = size;
+ }
+ else
+ {
+ parser->single_block = 1;
+ parser->private_dict = parser->base_dict;
+ parser->private_len = size;
+ parser->base_dict = 0;
+ parser->base_len = 0;
+ }
+
+ /* now determine whether the private dictionary is encoded in binary */
+ /* or hexadecimal ASCII format -- decode it accordingly */
+
+ /* we need to access the next 4 bytes (after the final \r following */
+ /* the `eexec' keyword); if they all are hexadecimal digits, then */
+ /* we have a case of ASCII storage */
+
+ if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
+ hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
+
+ /* binary encoding -- `simply' copy the private dict */
+ MEM_Copy( parser->private_dict, cur, size );
+
+ else
+ {
+ /* ASCII hexadecimal encoding */
+
+ FT_Byte* write;
+ FT_Int count;
+
+
+ write = parser->private_dict;
+ count = 0;
+
+ for ( ;cur < limit; cur++ )
+ {
+ int hex1;
+
+
+ /* check for newline */
+ if ( cur[0] == '\r' || cur[0] == '\n' )
+ continue;
+
+ /* exit if we have a non-hexadecimal digit that isn't a newline */
+ hex1 = hexa_value( cur[0] );
+ if ( hex1 < 0 || cur + 1 >= limit )
+ break;
+
+ /* otherwise, store byte */
+ *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
+ count++;
+ cur++;
+ }
+
+ /* put a safeguard */
+ parser->private_len = write - parser->private_dict;
+ *write++ = 0;
+ }
+ }
+
+ /* we now decrypt the encoded binary private dictionary */
+ T1_Decrypt( parser->private_dict, parser->private_len, 55665 );
+ parser->root.base = parser->private_dict;
+ parser->root.cursor = parser->private_dict;
+ parser->root.limit = parser->root.cursor + parser->private_len;
+
+ Fail:
+ Exit:
+ return error;
+ }
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1parse.h
@@ -1,0 +1,140 @@
+/***************************************************************************/
+/* */
+/* t1parse.h */
+/* */
+/* Type 1 parser (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 T1PARSE_H
+#define T1PARSE_H
+
+#include <freetype/internal/t1types.h>
+#include <freetype/internal/ftstream.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+ /*************************************************************************/
+ /* */
+ /* <Struct> */
+ /* T1_ParserRec */
+ /* */
+ /* <Description> */
+ /* A T1_ParserRec is an object used to parse a Type 1 fonts very */
+ /* quickly. */
+ /* */
+ /* <Fields> */
+ /* root :: The root parser. */
+ /* */
+ /* stream :: The current input stream. */
+ /* */
+ /* base_dict :: A pointer to the top-level dictionary. */
+ /* */
+ /* base_len :: The length in bytes of the top dictionary. */
+ /* */
+ /* private_dict :: A pointer to the private dictionary. */
+ /* */
+ /* private_len :: The length in bytes of the private dictionary. */
+ /* */
+ /* in_pfb :: A boolean. Indicates that we are handling a PFB */
+ /* file. */
+ /* */
+ /* in_memory :: A boolean. Indicates a memory-based stream. */
+ /* */
+ /* single_block :: A boolean. Indicates that the private dictionary */
+ /* is stored in lieu of the base dictionary. */
+ /* */
+ typedef struct T1_ParserRec_
+ {
+ T1_Parser root;
+ FT_Stream stream;
+
+ FT_Byte* base_dict;
+ FT_Int base_len;
+
+ FT_Byte* private_dict;
+ FT_Int private_len;
+
+ FT_Byte in_pfb;
+ FT_Byte in_memory;
+ FT_Byte single_block;
+
+ } T1_ParserRec;
+
+
+#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
+#define T1_Done_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.done ) \
+ (p)->funcs.done( p ); \
+ } while ( 0 )
+#define T1_Release_Table( p ) \
+ do \
+ { \
+ if ( (p)->funcs.release ) \
+ (p)->funcs.release( p ); \
+ } while ( 0 )
+
+
+#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
+#define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
+
+#define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
+#define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
+
+#define T1_ToCoordArray( p, m, c ) \
+ (p)->root.funcs.to_coord_array( &(p)->root, m, c )
+#define T1_ToFixedArray( p, m, f, t ) \
+ (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
+#define T1_ToToken( p, t ) \
+ (p)->root.funcs.to_token( &(p)->root, t )
+#define T1_ToTokenArray( p, t, m, c ) \
+ (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
+
+#define T1_Load_Field( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
+#define T1_Load_Field_Table( p, f, o, m, pf ) \
+ (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
+
+
+ LOCAL_DEF
+ FT_Error T1_New_Parser( T1_ParserRec* parser,
+ FT_Stream stream,
+ FT_Memory memory,
+ PSAux_Interface* psaux );
+
+ LOCAL_DEF
+ FT_Error T1_Get_Private_Dict( T1_ParserRec* parser );
+
+ LOCAL_DEF
+ void T1_Decrypt( FT_Byte* buffer,
+ FT_Int length,
+ FT_UShort seed );
+
+ LOCAL_DEF
+ void T1_Done_Parser( T1_ParserRec* parser );
+
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+#endif /* T1PARSE_H */
+
+
+/* END */
--- /dev/null
+++ b/src/type1/t1tokens.h
@@ -1,0 +1,73 @@
+/***************************************************************************/
+/* */
+/* t1tokens.h */
+/* */
+/* Type 1 tokenizer (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. */
+/* */
+/***************************************************************************/
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_FontInfo
+#undef T1CODE
+#define T1CODE t1_field_font_info
+
+ T1_FIELD_STRING( "version", version )
+ T1_FIELD_STRING( "Notice", notice )
+ T1_FIELD_STRING( "FullName", full_name )
+ T1_FIELD_STRING( "FamilyName", family_name )
+ T1_FIELD_STRING( "Weight", weight )
+
+ T1_FIELD_NUM ( "ItalicAngle", italic_angle )
+ T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch )
+ T1_FIELD_NUM ( "UnderlinePosition", underline_position )
+ T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_Private
+#undef T1CODE
+#define T1CODE t1_field_private
+
+ T1_FIELD_NUM ( "UniqueID", unique_id )
+ T1_FIELD_NUM ( "lenIV", lenIV )
+ T1_FIELD_NUM ( "LanguageGroup", language_group )
+ T1_FIELD_NUM ( "password", password )
+
+ T1_FIELD_FIXED ( "BlueScale", blue_scale )
+ T1_FIELD_NUM ( "BlueShift", blue_shift )
+ T1_FIELD_NUM ( "BlueFuzz", blue_fuzz )
+
+ T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
+ T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
+ T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
+ T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
+
+ T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 )
+ T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
+ T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
+
+ T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
+ T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
+
+
+#undef FT_STRUCTURE
+#define FT_STRUCTURE T1_Font
+#undef T1CODE
+#define T1CODE t1_field_font_dict
+
+ T1_FIELD_NUM( "PaintType", paint_type )
+ T1_FIELD_NUM( "FontType", font_type )
+ T1_FIELD_NUM( "StrokeWidth", stroke_width )
+
+
+/* END */
--- a/src/type1/type1.c
+++ b/src/type1/type1.c
@@ -2,7 +2,7 @@
/* */
/* type1.c */
/* */
-/* FreeType experimental Type 1 driver component (body only). */
+/* FreeType Type 1 driver component (body only). */
/* */
/* Copyright 1996-2000 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
@@ -21,26 +21,26 @@
#ifdef FT_FLAT_COMPILE
-#include "z1parse.c"
-#include "z1load.c"
-#include "z1objs.c"
-#include "z1driver.c"
-#include "z1gload.c"
+#include "t1parse.c"
+#include "t1load.c"
+#include "t1objs.c"
+#include "t1driver.c"
+#include "t1gload.c"
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-#include "z1afm.c"
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include "t1afm.c"
#endif
#else /* FT_FLAT_COMPILE */
-#include <type1/z1parse.c>
-#include <type1/z1load.c>
-#include <type1/z1objs.c>
-#include <type1/z1driver.c>
-#include <type1/z1gload.c>
+#include <type1/t1parse.c>
+#include <type1/t1load.c>
+#include <type1/t1objs.c>
+#include <type1/t1driver.c>
+#include <type1/t1gload.c>
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-#include <type1/z1afm.c>
+#ifndef T1_CONFIG_OPTION_NO_AFM
+#include <type1/t1afm.c>
#endif
#endif /* FT_FLAT_COMPILE */
--- a/src/type1/z1afm.c
+++ /dev/null
@@ -1,293 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1afm.c */
-/* */
-/* AFM support for Type 1 fonts (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. */
-/* */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1afm.h"
-
-#else
-
-#include <type1/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1types.h>
-
-#include <stdlib.h> /* for qsort() */
-#include <string.h> /* for strcmp() */
-#include <ctype.h> /* for isalnum() */
-
-
- /*************************************************************************/
- /* */
- /* 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_z1afm
-
-
- LOCAL_FUNC
- void Z1_Done_AFM( FT_Memory memory,
- Z1_AFM* afm )
- {
- FREE( afm->kern_pairs );
- afm->num_pairs = 0;
- }
-
-
-#undef IS_KERN_PAIR
-#define IS_KERN_PAIR( p ) ( p[0] == 'K' && p[1] == 'P' )
-
-#define IS_ALPHANUM( c ) ( isalnum( c ) || \
- c == '_' || \
- c == '.' )
-
-
- /* read a glyph name and return the equivalent glyph index */
- static
- FT_UInt afm_atoindex( FT_Byte** start,
- FT_Byte* limit,
- T1_Font* type1 )
- {
- FT_Byte* p = *start;
- FT_Int len;
- FT_UInt result = 0;
- char temp[64];
-
-
- /* skip whitespace */
- while ( ( *p == ' ' || *p == '\t' || *p == ':' || *p == ';' ) &&
- p < limit )
- p++;
- *start = p;
-
- /* now, read glyph name */
- while ( IS_ALPHANUM( *p ) && p < limit )
- p++;
-
- len = p - *start;
-
- if ( len > 0 && len < 64 )
- {
- FT_Int n;
-
-
- /* copy glyph name to intermediate array */
- MEM_Copy( temp, *start, len );
- temp[len] = 0;
-
- /* lookup glyph name in face array */
- for ( n = 0; n < type1->num_glyphs; n++ )
- {
- char* gname = (char*)type1->glyph_names[n];
-
-
- if ( gname && gname[0] == temp[0] && strcmp( gname, temp ) == 0 )
- {
- result = n;
- break;
- }
- }
- }
- *start = p;
- return result;
- }
-
-
- /* read an integer */
- static
- int afm_atoi( FT_Byte** start,
- FT_Byte* limit )
- {
- FT_Byte* p = *start;
- int sum = 0;
- int sign = 1;
-
-
- /* skip everything that is not a number */
- while ( p < limit && !isdigit( *p ) )
- {
- sign = 1;
- if ( *p == '-' )
- sign = -1;
-
- p++;
- }
-
- while ( p < limit && isdigit( *p ) )
- {
- sum = sum * 10 + ( *p - '0' );
- p++;
- }
- *start = p;
-
- return sum * sign;
- }
-
-
-#undef KERN_INDEX
-#define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
-
-
- /* compare two kerning pairs */
- LOCAL_FUNC_X
- int compare_kern_pairs( const void* a,
- const void* b )
- {
- Z1_Kern_Pair* pair1 = (Z1_Kern_Pair*)a;
- Z1_Kern_Pair* pair2 = (Z1_Kern_Pair*)b;
-
- FT_ULong index1 = KERN_INDEX( pair1->glyph1, pair1->glyph2 );
- FT_ULong index2 = KERN_INDEX( pair2->glyph1, pair2->glyph2 );
-
-
- return ( index1 - index2 );
- }
-
-
- /* parse an AFM file -- for now, only read the kerning pairs */
- LOCAL_FUNC
- FT_Error Z1_Read_AFM( FT_Face t1_face,
- FT_Stream stream )
- {
- FT_Error error;
- FT_Memory memory = stream->memory;
- FT_Byte* start;
- FT_Byte* limit;
- FT_Byte* p;
- FT_Int count = 0;
- Z1_Kern_Pair* pair;
- T1_Font* type1 = &((T1_Face)t1_face)->type1;
- Z1_AFM* afm = 0;
-
-
- if ( ACCESS_Frame( stream->size ) )
- return error;
-
- start = (FT_Byte*)stream->cursor;
- limit = (FT_Byte*)stream->limit;
- p = start;
-
- /* we are now going to count the occurences of `KP' or `KPX' in */
- /* the AFM file */
- count = 0;
- for ( p = start; p < limit - 3; p++ )
- {
- if ( IS_KERN_PAIR( p ) )
- count++;
- }
-
- /* Actually, kerning pairs are simply optional! */
- if ( count == 0 )
- goto Exit;
-
- /* allocate the pairs */
- if ( ALLOC( afm, sizeof ( *afm ) ) ||
- ALLOC_ARRAY( afm->kern_pairs, count, Z1_Kern_Pair ) )
- goto Exit;
-
- /* now, read each kern pair */
- pair = afm->kern_pairs;
- afm->num_pairs = count;
-
- /* save in face object */
- ((T1_Face)t1_face)->afm_data = afm;
-
- for ( p = start; p < limit - 3; p++ )
- {
- if ( IS_KERN_PAIR( p ) )
- {
- FT_Byte* q;
-
-
- /* skip keyword (KP or KPX) */
- q = p + 2;
- if ( *q == 'X' )
- q++;
-
- pair->glyph1 = afm_atoindex( &q, limit, type1 );
- pair->glyph2 = afm_atoindex( &q, limit, type1 );
- pair->kerning.x = afm_atoi( &q, limit );
-
- pair->kerning.y = 0;
- if ( p[2] != 'X' )
- pair->kerning.y = afm_atoi( &q, limit );
-
- pair++;
- }
- }
-
- /* now, sort the kern pairs according to their glyph indices */
- qsort( afm->kern_pairs, count, sizeof ( Z1_Kern_Pair ),
- compare_kern_pairs );
-
- Exit:
- if ( error )
- FREE( afm );
-
- FORGET_Frame();
-
- return error;
- }
-
-
- /* find the kerning for a given glyph pair */
- LOCAL_FUNC
- void Z1_Get_Kerning( Z1_AFM* afm,
- FT_UInt glyph1,
- FT_UInt glyph2,
- FT_Vector* kerning )
- {
- Z1_Kern_Pair *min, *mid, *max;
- FT_ULong index = KERN_INDEX( glyph1, glyph2 );
-
-
- /* simple binary search */
- min = afm->kern_pairs;
- max = min + afm->num_pairs - 1;
-
- while ( min <= max )
- {
- FT_ULong midi;
-
-
- mid = min + ( max - min ) / 2;
- midi = KERN_INDEX( mid->glyph1, mid->glyph2 );
-
- if ( midi == index )
- {
- *kerning = mid->kerning;
- return;
- }
-
- if ( midi < index )
- min = mid + 1;
- else
- max = mid - 1;
- }
-
- kerning->x = 0;
- kerning->y = 0;
- }
-
-
-/* END */
--- a/src/type1/z1afm.h
+++ /dev/null
@@ -1,79 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1afm.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. */
-/* */
-/***************************************************************************/
-
-
-#ifndef Z1AFM_H
-#define Z1AFM_H
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1objs.h"
-
-#else
-
-#include <type1/z1objs.h>
-
-#endif
-
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- typedef struct Z1_Kern_Pair_
- {
- FT_UInt glyph1;
- FT_UInt glyph2;
- FT_Vector kerning;
-
- } Z1_Kern_Pair;
-
-
- typedef struct Z1_AFM_
- {
- FT_Int num_pairs;
- Z1_Kern_Pair* kern_pairs;
-
- } Z1_AFM;
-
-
- LOCAL_DEF
- FT_Error Z1_Read_AFM( FT_Face face,
- FT_Stream stream );
-
- LOCAL_DEF
- void Z1_Done_AFM( FT_Memory memory,
- Z1_AFM* afm );
-
- LOCAL_DEF
- void Z1_Get_Kerning( Z1_AFM* afm,
- FT_UInt glyph1,
- FT_UInt glyph2,
- FT_Vector* kerning );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* Z1AFM_H */
-
-
-/* END */
--- a/src/type1/z1driver.c
+++ /dev/null
@@ -1,340 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1driver.c */
-/* */
-/* Experimental 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. */
-/* */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1driver.h"
-#include "z1gload.h"
-#include "z1load.h"
-#include "z1afm.h"
-
-#else
-
-#include <type1/z1driver.h>
-#include <type1/z1gload.h>
-#include <type1/z1load.h>
-#include <type1/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/psnames.h>
-
-#include <string.h> /* for strcmp() */
-
-
- /*************************************************************************/
- /* */
- /* 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_z1driver
-
-
- static
- FT_Error get_z1_glyph_name( T1_Face face,
- FT_UInt glyph_index,
- FT_Pointer buffer,
- FT_UInt buffer_max )
- {
- FT_String* gname;
-
-
- gname = face->type1.glyph_names[glyph_index];
-
- if ( buffer_max > 0 )
- {
- FT_UInt len = strlen( gname );
-
-
- if (len >= buffer_max)
- len = buffer_max - 1;
-
- MEM_Copy( buffer, gname, len );
- ((FT_Byte*)buffer)[len] = 0;
- }
-
- return T1_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Interface */
- /* */
- /* <Description> */
- /* Each driver can provide one or more extensions to the base */
- /* FreeType API. These can be used to access format specific */
- /* features (e.g., all TrueType/OpenType resources share a common */
- /* file structure and common tables which can be accessed through the */
- /* `sfnt' interface), or more simply generic ones (e.g., the */
- /* `postscript names' interface which can be used to retrieve the */
- /* PostScript name of a given glyph index). */
- /* */
- /* <InOut> */
- /* driver :: A handle to a driver object. */
- /* */
- /* <Input> */
- /* interface :: A string designing the interface. Examples are */
- /* `sfnt', `post_names', `charmaps', etc. */
- /* */
- /* <Return> */
- /* A typeless pointer to the extension's interface (normally a table */
- /* of function pointers). Returns NULL if the requested extension */
- /* isn't available (i.e., wasn't compiled in the driver at build */
- /* time). */
- /* */
- static
- FT_Module_Interface Get_Interface( FT_Driver driver,
- const FT_String* interface )
- {
- FT_UNUSED( driver );
- FT_UNUSED( interface );
-
- if ( strcmp( (const char*)interface, "glyph_name" ) == 0 )
- return (FT_Module_Interface)get_z1_glyph_name;
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
- if ( strcmp( (const char*)interface, "get_mm" ) == 0 )
- return (FT_Module_Interface)Z1_Get_Multi_Master;
-
- if ( strcmp( (const char*)interface, "set_mm_design") == 0 )
- return (FT_Module_Interface)Z1_Set_MM_Design;
-
- if ( strcmp( (const char*)interface, "set_mm_blend") == 0 )
- return (FT_Module_Interface)Z1_Set_MM_Blend;
-#endif
- return 0;
- }
-
-
-#ifndef Z1_CONFIG_OPTION_NO_AFM
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Kerning */
- /* */
- /* <Description> */
- /* A driver method used to return the kerning vector between two */
- /* glyphs of the same face. */
- /* */
- /* <Input> */
- /* face :: A handle to the source face object. */
- /* */
- /* left_glyph :: The index of the left glyph in the kern pair. */
- /* */
- /* right_glyph :: The index of the right glyph in the kern pair. */
- /* */
- /* <Output> */
- /* kerning :: The kerning vector. This is in font units for */
- /* scalable formats, and in pixels for fixed-sizes */
- /* formats. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- /* <Note> */
- /* Only horizontal layouts (left-to-right & right-to-left) are */
- /* supported by this function. Other layouts, or more sophisticated */
- /* kernings are out of scope of this method (the basic driver */
- /* interface is meant to be simple). */
- /* */
- /* They can be implemented by format-specific interfaces. */
- /* */
- static
- FT_Error Get_Kerning( T1_Face face,
- FT_UInt left_glyph,
- FT_UInt right_glyph,
- FT_Vector* kerning )
- {
- Z1_AFM* afm;
-
-
- kerning->x = 0;
- kerning->y = 0;
-
- afm = (Z1_AFM*)face->afm_data;
- if ( afm )
- Z1_Get_Kerning( afm, left_glyph, right_glyph, kerning );
-
- return T1_Err_Ok;
- }
-
-
-#endif /* T1_CONFIG_OPTION_NO_AFM */
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Get_Char_Index */
- /* */
- /* <Description> */
- /* Uses a charmap to return a given character code's glyph index. */
- /* */
- /* <Input> */
- /* charmap :: A handle to the source charmap object. */
- /* charcode :: The character code. */
- /* */
- /* <Return> */
- /* Glyph index. 0 means `undefined character code'. */
- /* */
- static
- FT_UInt Get_Char_Index( FT_CharMap charmap,
- FT_Long charcode )
- {
- T1_Face face;
- FT_UInt result = 0;
- PSNames_Interface* psnames;
-
-
- face = (T1_Face)charmap->face;
- psnames = (PSNames_Interface*)face->psnames;
- if ( psnames )
- switch ( charmap->encoding )
- {
- /*******************************************************************/
- /* */
- /* Unicode encoding support */
- /* */
- case ft_encoding_unicode:
- /* use the `PSNames' module to synthetize the Unicode charmap */
- result = psnames->lookup_unicode( &face->unicode_map,
- (FT_ULong)charcode );
-
- /* the function returns 0xFFFF if the Unicode charcode has */
- /* no corresponding glyph */
- if ( result == 0xFFFF )
- result = 0;
- goto Exit;
-
- /*******************************************************************/
- /* */
- /* Custom Type 1 encoding */
- /* */
- case ft_encoding_adobe_custom:
- {
- T1_Encoding* encoding = &face->type1.encoding;
-
-
- if ( charcode >= encoding->code_first &&
- charcode <= encoding->code_last )
- result = encoding->char_index[charcode];
- goto Exit;
- }
-
- /*******************************************************************/
- /* */
- /* Adobe Standard & Expert encoding support */
- /* */
- default:
- if ( charcode < 256 )
- {
- FT_UInt code;
- FT_Int n;
- const char* glyph_name;
-
-
- code = psnames->adobe_std_encoding[charcode];
- if ( charmap->encoding == ft_encoding_adobe_expert )
- code = psnames->adobe_expert_encoding[charcode];
-
- glyph_name = psnames->adobe_std_strings( code );
- if ( !glyph_name )
- break;
-
- for ( n = 0; n < face->type1.num_glyphs; n++ )
- {
- const char* gname = face->type1.glyph_names[n];
-
-
- if ( gname && gname[0] == glyph_name[0] &&
- strcmp( gname, glyph_name ) == 0 )
- {
- result = n;
- break;
- }
- }
- }
- }
- Exit:
- return result;
- }
-
-
- FT_CPLUSPLUS( const FT_Driver_Class ) t1_driver_class =
- {
- {
- ft_module_font_driver | ft_module_driver_scalable,
- sizeof( FT_DriverRec ),
-
- "type1",
- 0x10000L,
- 0x20000L,
-
- 0, /* format interface */
-
- (FT_Module_Constructor)Z1_Init_Driver,
- (FT_Module_Destructor) Z1_Done_Driver,
- (FT_Module_Requester) Get_Interface,
- },
-
- sizeof( T1_FaceRec ),
- sizeof( Z1_SizeRec ),
- sizeof( Z1_GlyphSlotRec ),
-
- (FTDriver_initFace) Z1_Init_Face,
- (FTDriver_doneFace) Z1_Done_Face,
- (FTDriver_initSize) 0,
- (FTDriver_doneSize) 0,
- (FTDriver_initGlyphSlot)0,
- (FTDriver_doneGlyphSlot)0,
-
- (FTDriver_setCharSizes) 0,
- (FTDriver_setPixelSizes)0,
- (FTDriver_loadGlyph) Z1_Load_Glyph,
- (FTDriver_getCharIndex) Get_Char_Index,
-
-#ifdef Z1_CONFIG_OPTION_NO_AFM
- (FTDriver_getKerning) 0,
- (FTDriver_attachFile) 0,
-#else
- (FTDriver_getKerning) Get_Kerning,
- (FTDriver_attachFile) Z1_Read_AFM,
-#endif
- (FTDriver_getAdvances) 0
- };
-
-
-#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS
-
- EXPORT_FUNC( const FT_Driver_Class* ) getDriverClass( void )
- {
- return &t1z_driver_class;
- }
-
-#endif /* FT_CONFIG_OPTION_DYNAMIC_DRIVERS */
-
-
-/* END */
--- a/src/type1/z1driver.h
+++ /dev/null
@@ -1,39 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1driver.h */
-/* */
-/* High-level experimental 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. */
-/* */
-/***************************************************************************/
-
-
-#ifndef Z1DRIVER_H
-#define Z1DRIVER_H
-
-#include <freetype/internal/ftdriver.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- FT_EXPORT_VAR( const FT_Driver_Class ) t1_driver_class;
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* Z1DRIVER_H */
-
-
-/* END */
--- a/src/type1/z1gload.c
+++ /dev/null
@@ -1,309 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1gload.c */
-/* */
-/* Experimental 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. */
-/* */
-/***************************************************************************/
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1gload.h"
-
-#else
-
-#include <type1/z1gload.h>
-
-#endif
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/ftoutln.h>
-#include <freetype/internal/psaux.h>
-
-
-#include <string.h> /* for strcmp() */
-
-
- /*************************************************************************/
- /* */
- /* 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_z1gload
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /********** *********/
- /********** 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. *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- LOCAL_FUNC_X
- FT_Error Z1_Parse_Glyph( T1_Decoder* decoder,
- FT_UInt glyph_index )
- {
- T1_Face face = (T1_Face)decoder->builder.face;
- T1_Font* type1 = &face->type1;
-
-
- decoder->font_matrix = type1->font_matrix;
- decoder->font_offset = type1->font_offset;
-
- return decoder->funcs.parse_charstrings(
- decoder,
- type1->charstrings [glyph_index],
- type1->charstrings_len[glyph_index] );
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Compute_Max_Advance( T1_Face face,
- FT_Int* max_advance )
- {
- FT_Error error;
- T1_Decoder decoder;
- FT_Int glyph_index;
- T1_Font* type1 = &face->type1;
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
-
-
- *max_advance = 0;
-
- /* initialize load decoder */
- error = psaux->t1_decoder_funcs->init( &decoder,
- (FT_Face)face,
- 0, /* size */
- 0, /* glyph slot */
- (FT_Byte**)type1->glyph_names,
- face->blend,
- Z1_Parse_Glyph );
- if ( error )
- return error;
-
- decoder.builder.metrics_only = 1;
- decoder.builder.load_points = 0;
-
- decoder.num_subrs = type1->num_subrs;
- decoder.subrs = type1->subrs;
- decoder.subrs_len = type1->subrs_len;
-
- /* for each glyph, parse the glyph charstring and extract */
- /* the advance width */
- for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
- {
- /* now get load the unscaled outline */
- error = Z1_Parse_Glyph( &decoder, glyph_index );
- /* ignore the error if one occured - skip to next glyph */
- }
-
- *max_advance = decoder.builder.advance.x;
- return FT_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' *********/
- /********** *********/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
- LOCAL_FUNC
- FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
- Z1_Size size,
- FT_Int glyph_index,
- FT_Int load_flags )
- {
- FT_Error error;
- T1_Decoder decoder;
- T1_Face face = (T1_Face)glyph->root.face;
- FT_Bool hinting;
- T1_Font* type1 = &face->type1;
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
- const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
-
- FT_Matrix font_matrix;
- FT_Vector font_offset;
-
- if ( load_flags & FT_LOAD_NO_RECURSE )
- load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
-
- glyph->x_scale = size->root.metrics.x_scale;
- glyph->y_scale = size->root.metrics.y_scale;
-
- glyph->root.outline.n_points = 0;
- glyph->root.outline.n_contours = 0;
-
- hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
- ( load_flags & FT_LOAD_NO_HINTING ) == 0;
-
- glyph->root.format = ft_glyph_format_outline;
-
- error = decoder_funcs->init( &decoder,
- (FT_Face)face,
- (FT_Size)size,
- (FT_GlyphSlot)glyph,
- (FT_Byte**)type1->glyph_names,
- face->blend,
- Z1_Parse_Glyph );
- if ( error )
- goto Exit;
-
- decoder.builder.no_recurse = ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
-
- decoder.num_subrs = type1->num_subrs;
- decoder.subrs = type1->subrs;
- decoder.subrs_len = type1->subrs_len;
-
-
- /* now load the unscaled outline */
- error = Z1_Parse_Glyph( &decoder, glyph_index );
- if ( error )
- goto Exit;
-
- font_matrix = decoder.font_matrix;
- font_offset = decoder.font_offset;
-
- /* save new glyph tables */
- decoder_funcs->done( &decoder );
-
- /* 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 )
- {
- glyph->root.outline.flags &= ft_outline_owner;
- glyph->root.outline.flags |= ft_outline_reverse_fill;
-
- /* for composite glyphs, return only left side bearing and */
- /* advance width */
- if ( load_flags & FT_LOAD_NO_RECURSE )
- {
- glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
- glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
- }
- else
- {
- FT_BBox cbox;
- FT_Glyph_Metrics* metrics = &glyph->root.metrics;
-
-
- /* copy the _unscaled_ advance width */
- metrics->horiAdvance = decoder.builder.advance.x;
- glyph->root.linearHoriAdvance = decoder.builder.advance.x;
-
- /* make up vertical metrics */
- metrics->vertBearingX = 0;
- metrics->vertBearingY = 0;
- metrics->vertAdvance = 0;
-
- glyph->root.linearVertAdvance = 0;
-
- glyph->root.format = ft_glyph_format_outline;
-
- if ( size && size->root.metrics.y_ppem < 24 )
- glyph->root.outline.flags |= ft_outline_high_precision;
-
- /* apply the font matrix */
- FT_Outline_Transform( &glyph->root.outline, &font_matrix );
-
- FT_Outline_Translate( &glyph->root.outline,
- font_offset.x,
- font_offset.y );
-
-#if 0
-
- glyph->root.outline.second_pass = TRUE;
- glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
- glyph->root.outline.dropout_mode = 2;
-
-#endif /* 0 */
-
- if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
- {
- /* scale the outline and the metrics */
- FT_Int n;
- FT_Outline* cur = decoder.builder.base;
- FT_Vector* vec = cur->points;
- FT_Fixed x_scale = glyph->x_scale;
- FT_Fixed y_scale = glyph->y_scale;
-
-
- /* First of all, scale the points */
- for ( n = cur->n_points; n > 0; n--, vec++ )
- {
- vec->x = FT_MulFix( vec->x, x_scale );
- vec->y = FT_MulFix( vec->y, y_scale );
- }
-
- FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
- /* Then scale the metrics */
- metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
- metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
-
- metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
- metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
- }
-
- /* compute the other metrics */
- FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
- /* grid fit the bounding box if necessary */
- if ( hinting )
- {
- cbox.xMin &= -64;
- cbox.yMin &= -64;
- cbox.xMax = ( cbox.xMax+63 ) & -64;
- cbox.yMax = ( cbox.yMax+63 ) & -64;
- }
-
- metrics->width = cbox.xMax - cbox.xMin;
- metrics->height = cbox.yMax - cbox.yMin;
-
- metrics->horiBearingX = cbox.xMin;
- metrics->horiBearingY = cbox.yMax;
- }
- }
-
- Exit:
- return error;
- }
-
-
-/* END */
--- a/src/type1/z1gload.h
+++ /dev/null
@@ -1,58 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1gload.h */
-/* */
-/* Experimental 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. */
-/* */
-/***************************************************************************/
-
-
-#ifndef Z1GLOAD_H
-#define Z1GLOAD_H
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1objs.h"
-
-#else
-
-#include <type1/z1objs.h>
-
-#endif
-
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- LOCAL_DEF
- FT_Error Z1_Compute_Max_Advance( T1_Face face,
- FT_Int* max_advance );
-
- LOCAL_DEF
- FT_Error Z1_Load_Glyph( Z1_GlyphSlot glyph,
- Z1_Size size,
- FT_Int glyph_index,
- FT_Int load_flags );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* Z1GLOAD_H */
-
-
-/* END */
--- a/src/type1/z1load.c
+++ /dev/null
@@ -1,1702 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1load.c */
-/* */
-/* Experimental Type 1 font 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. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* This is the new and improved Type 1 data loader for FreeType 2. The */
- /* old loader has several problems: it is slow, complex, difficult to */
- /* maintain, and contains incredible hacks to make it accept some */
- /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */
- /* the Type 1 fonts on my machine still aren't loaded correctly by it. */
- /* */
- /* This version is much simpler, much faster and also easier to read and */
- /* maintain by a great order of magnitude. The idea behind it is to */
- /* _not_ try to read the Type 1 token stream with a state machine (i.e. */
- /* a Postscript-like interpreter) but rather to perform simple pattern */
- /* matching. */
- /* */
- /* Indeed, nearly all data definitions follow a simple pattern like */
- /* */
- /* ... /Field <data> ... */
- /* */
- /* where <data> can be a number, a boolean, a string, or an array of */
- /* numbers. There are a few exceptions, namely the encoding, font name, */
- /* charstrings, and subrs; they are handled with a special pattern */
- /* matching routine. */
- /* */
- /* All other common cases are handled very simply. The matching rules */
- /* are defined in the file `t1tokens.h' through the use of several */
- /* macros calls PARSE_XXX. */
- /* */
- /* This file is included twice here; the first time to generate parsing */
- /* callback functions, the second to generate a table of keywords (with */
- /* pointers to the associated callback). */
- /* */
- /* The function `parse_dict' simply scans *linearly* a given dictionary */
- /* (either the top-level or private one) and calls the appropriate */
- /* callback when it encounters an immediate keyword. */
- /* */
- /* This is by far the fastest way one can find to parse and read all */
- /* data. */
- /* */
- /* This led to tremendous code size reduction. Note that later, the */
- /* glyph loader will also be _greatly_ simplified, and the automatic */
- /* hinter will replace the clumsy `t1hinter'. */
- /* */
- /*************************************************************************/
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/config/ftconfig.h>
-#include <freetype/ftmm.h>
-
-#include <freetype/internal/t1types.h>
-#include <freetype/internal/t1errors.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1load.h"
-
-#else
-
-#include <type1/z1load.h>
-
-#endif
-
-
-#include <string.h> /* for strncmp(), strcmp() */
-#include <ctype.h> /* for isalnum() */
-
-
- /*************************************************************************/
- /* */
- /* 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_z1load
-
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** MULTIPLE MASTERS SUPPORT *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
- static
- FT_Error t1_allocate_blend( T1_Face face,
- FT_UInt num_designs,
- FT_UInt num_axis )
- {
- T1_Blend* blend;
- FT_Memory memory = face->root.memory;
- FT_Error error = 0;
-
-
- blend = face->blend;
- if ( !blend )
- {
- if ( ALLOC( blend, sizeof ( *blend ) ) )
- goto Exit;
-
- face->blend = blend;
- }
-
- /* allocate design data if needed */
- if ( num_designs > 0 )
- {
- if ( blend->num_designs == 0 )
- {
- FT_UInt nn;
-
-
- /* allocate the blend `private' and `font_info' dictionaries */
- if ( ALLOC_ARRAY( blend->font_infos[1], num_designs, T1_FontInfo ) ||
- ALLOC_ARRAY( blend->privates[1], num_designs, T1_Private ) ||
- ALLOC_ARRAY( blend->weight_vector, num_designs * 2, FT_Fixed ) )
- goto Exit;
-
- blend->default_weight_vector = blend->weight_vector + num_designs;
-
- blend->font_infos[0] = &face->type1.font_info;
- blend->privates [0] = &face->type1.private_dict;
-
- for ( nn = 2; nn <= num_designs; nn++ )
- {
- blend->privates[nn] = blend->privates [nn - 1] + 1;
- blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
- }
-
- blend->num_designs = num_designs;
- }
- else if ( blend->num_designs != num_designs )
- goto Fail;
- }
-
- /* allocate axis data if needed */
- if ( num_axis > 0 )
- {
- if ( blend->num_axis != 0 && blend->num_axis != num_axis )
- goto Fail;
-
- blend->num_axis = num_axis;
- }
-
- /* allocate the blend design pos table if needed */
- num_designs = blend->num_designs;
- num_axis = blend->num_axis;
- if ( num_designs && num_axis && blend->design_pos[0] == 0 )
- {
- FT_UInt n;
-
-
- if ( ALLOC_ARRAY( blend->design_pos[0],
- num_designs * num_axis, FT_Fixed ) )
- goto Exit;
-
- for ( n = 1; n < num_designs; n++ )
- blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
- }
-
- Exit:
- return error;
-
- Fail:
- error = -1;
- goto Exit;
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Get_Multi_Master( T1_Face face,
- FT_Multi_Master* master )
- {
- T1_Blend* blend = face->blend;
- FT_UInt n;
- FT_Error error;
-
-
- error = T1_Err_Invalid_Argument;
-
- if ( blend )
- {
- master->num_axis = blend->num_axis;
- master->num_designs = blend->num_designs;
-
- for ( n = 0; n < blend->num_axis; n++ )
- {
- FT_MM_Axis* axis = master->axis + n;
- T1_DesignMap* map = blend->design_map + n;
-
-
- axis->name = blend->axis_names[n];
- axis->minimum = map->design_points[0];
- axis->maximum = map->design_points[map->num_points - 1];
- }
- error = 0;
- }
- return error;
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Set_MM_Blend( T1_Face face,
- FT_UInt num_coords,
- FT_Fixed* coords )
- {
- T1_Blend* blend = face->blend;
- FT_Error error;
- FT_UInt n, m;
-
-
- error = T1_Err_Invalid_Argument;
-
- if ( blend && blend->num_axis == num_coords )
- {
- /* recompute the weight vector from the blend coordinates */
- error = FT_Err_Ok;
-
- for ( n = 0; n < blend->num_designs; n++ )
- {
- FT_Fixed result = 0x10000L; /* 1.0 fixed */
-
-
- for ( m = 0; m < blend->num_axis; m++ )
- {
- FT_Fixed factor;
-
-
- /* get current blend axis position */
- factor = coords[m];
- if ( factor < 0 ) factor = 0;
- if ( factor > 0x10000L ) factor = 0x10000L;
-
- if ( ( n & ( 1 << m ) ) == 0 )
- factor = 0x10000L - factor;
-
- result = FT_MulFix( result, factor );
- }
- blend->weight_vector[n] = result;
- }
-
- error = FT_Err_Ok;
- }
- return error;
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Set_MM_Design( T1_Face face,
- FT_UInt num_coords,
- FT_Long* coords )
- {
- T1_Blend* blend = face->blend;
- FT_Error error;
- FT_UInt n, p;
-
-
- error = T1_Err_Invalid_Argument;
- if ( blend && blend->num_axis == num_coords )
- {
- /* compute the blend coordinates through the blend design map */
- FT_Fixed final_blends[T1_MAX_MM_DESIGNS];
-
-
- for ( n = 0; n < blend->num_axis; n++ )
- {
- FT_Long design = coords[n];
- FT_Fixed the_blend;
- T1_DesignMap* map = blend->design_map + n;
- FT_Fixed* designs = map->design_points;
- FT_Fixed* blends = map->blend_points;
- FT_Int before = -1, after = -1;
-
- for ( p = 0; p < map->num_points; p++ )
- {
- FT_Fixed p_design = designs[p];
-
-
- /* exact match ? */
- if ( design == p_design )
- {
- the_blend = blends[p];
- goto Found;
- }
-
- if ( design < p_design )
- {
- after = p;
- break;
- }
-
- before = p;
- }
-
- /* now, interpolate if needed */
- if ( before < 0 )
- the_blend = blends[0];
-
- else if ( after < 0 )
- the_blend = blends[map->num_points - 1];
-
- else
- the_blend = FT_MulDiv( design - designs[before],
- blends [after] - blends [before],
- designs[after] - designs[before] );
-
- Found:
- final_blends[n] = the_blend;
- }
-
- error = Z1_Set_MM_Blend( face, num_coords, final_blends );
- }
-
- return error;
- }
-
-
- LOCAL_FUNC
- void Z1_Done_Blend( T1_Face face )
- {
- FT_Memory memory = face->root.memory;
- T1_Blend* blend = face->blend;
-
-
- if ( blend )
- {
- FT_UInt num_designs = blend->num_designs;
- FT_UInt num_axis = blend->num_axis;
- FT_UInt n;
-
-
- /* release design pos table */
- FREE( blend->design_pos[0] );
- for ( n = 1; n < num_designs; n++ )
- blend->design_pos[n] = 0;
-
- /* release blend `private' and `font info' dictionaries */
- FREE( blend->privates[1] );
- FREE( blend->font_infos[1] );
-
- for ( n = 0; n < num_designs; n++ )
- {
- blend->privates [n] = 0;
- blend->font_infos[n] = 0;
- }
-
- /* release weight vectors */
- FREE( blend->weight_vector );
- blend->default_weight_vector = 0;
-
- /* release axis names */
- for ( n = 0; n < num_axis; n++ )
- FREE( blend->axis_names[n] );
-
- /* release design map */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_DesignMap* dmap = blend->design_map + n;
-
-
- FREE( dmap->design_points );
- dmap->num_points = 0;
- }
-
- FREE( face->blend );
- }
- }
-
-
- static
- void parse_blend_axis_types( T1_Face face,
- Z1_Loader* loader )
- {
- T1_Token axis_tokens[ T1_MAX_MM_AXIS ];
- FT_Int n, num_axis;
- FT_Error error = 0;
- T1_Blend* blend;
- FT_Memory memory;
-
-
- /* take an array of objects */
- Z1_ToTokenArray( &loader->parser, axis_tokens,
- T1_MAX_MM_AXIS, &num_axis );
- if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
- {
- FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
- num_axis ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* allocate blend if necessary */
- error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
- if ( error )
- goto Exit;
-
- blend = face->blend;
- memory = face->root.memory;
-
- /* each token is an immediate containing the name of the axis */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_Token* token = axis_tokens + n;
- FT_Byte* name;
- FT_Int len;
-
- /* skip first slash, if any */
- if (token->start[0] == '/')
- token->start++;
-
- len = token->limit - token->start;
- if ( len <= 0 )
- {
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- if ( ALLOC( blend->axis_names[n], len + 1 ) )
- goto Exit;
-
- name = (FT_Byte*)blend->axis_names[n];
- MEM_Copy( name, token->start, len );
- name[len] = 0;
- }
-
- Exit:
- loader->parser.root.error = error;
- }
-
-
- static
- void parse_blend_design_positions( T1_Face face,
- Z1_Loader* loader )
- {
- T1_Token design_tokens[ T1_MAX_MM_DESIGNS ];
- FT_Int num_designs;
- FT_Int num_axis;
- Z1_Parser* parser = &loader->parser;
-
- FT_Error error = 0;
- T1_Blend* blend;
-
-
- /* get the array of design tokens - compute number of designs */
- Z1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
- if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
- {
- FT_ERROR(( "parse_blend_design_positions:" ));
- FT_ERROR(( " incorrect number of designs: %d\n",
- num_designs ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- {
- FT_Byte* old_cursor = parser->root.cursor;
- FT_Byte* old_limit = parser->root.limit;
- FT_UInt n;
-
-
- blend = face->blend;
- num_axis = 0; /* make compiler happy */
-
- for ( n = 0; n < (FT_UInt)num_designs; n++ )
- {
- T1_Token axis_tokens[ T1_MAX_MM_DESIGNS ];
- T1_Token* token;
- FT_Int axis, n_axis;
-
-
- /* read axis/coordinates tokens */
- token = design_tokens + n;
- parser->root.cursor = token->start - 1;
- parser->root.limit = token->limit + 1;
- Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
-
- if ( n == 0 )
- {
- num_axis = n_axis;
- error = t1_allocate_blend( face, num_designs, num_axis );
- if ( error )
- goto Exit;
- blend = face->blend;
- }
- else if ( n_axis != num_axis )
- {
- FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* now, read each axis token into the design position */
- for ( axis = 0; axis < n_axis; axis++ )
- {
- T1_Token* token2 = axis_tokens + axis;
-
-
- parser->root.cursor = token2->start;
- parser->root.limit = token2->limit;
- blend->design_pos[n][axis] = Z1_ToFixed( parser, 0 );
- }
- }
-
- loader->parser.root.cursor = old_cursor;
- loader->parser.root.limit = old_limit;
- }
-
- Exit:
- loader->parser.root.error = error;
- }
-
-
- static
- void parse_blend_design_map( T1_Face face,
- Z1_Loader* loader )
- {
- FT_Error error = 0;
- Z1_Parser* parser = &loader->parser;
- T1_Blend* blend;
- T1_Token axis_tokens[ T1_MAX_MM_AXIS ];
- FT_Int n, num_axis;
- FT_Byte* old_cursor;
- FT_Byte* old_limit;
- FT_Memory memory = face->root.memory;
-
-
- Z1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
- if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
- {
- FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
- num_axis ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
- old_cursor = parser->root.cursor;
- old_limit = parser->root.limit;
-
- error = t1_allocate_blend( face, 0, num_axis );
- if ( error )
- goto Exit;
- blend = face->blend;
-
- /* now, read each axis design map */
- for ( n = 0; n < num_axis; n++ )
- {
- T1_DesignMap* map = blend->design_map + n;
- T1_Token* token;
- FT_Int p, num_points;
-
-
- token = axis_tokens + n;
- parser->root.cursor = token->start;
- parser->root.limit = token->limit;
-
- /* count the number of map points */
- {
- FT_Byte* ptr = token->start;
- FT_Byte* limit = token->limit;
-
-
- num_points = 0;
- for ( ; ptr < limit; ptr++ )
- if ( ptr[0] == '[' )
- num_points++;
- }
- if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
- {
- FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- /* allocate design map data */
- if ( ALLOC_ARRAY( map->design_points, num_points * 2, FT_Fixed ) )
- goto Exit;
- map->blend_points = map->design_points + num_points;
- map->num_points = (FT_Byte)num_points;
-
- for ( p = 0; p < num_points; p++ )
- {
- map->design_points[p] = Z1_ToInt( parser );
- map->blend_points [p] = Z1_ToFixed( parser, 0 );
- }
- }
-
- parser->root.cursor = old_cursor;
- parser->root.limit = old_limit;
-
- Exit:
- parser->root.error = error;
- }
-
-
- static
- void parse_weight_vector( T1_Face face,
- Z1_Loader* loader )
- {
- FT_Error error = 0;
- Z1_Parser* parser = &loader->parser;
- T1_Blend* blend = face->blend;
- T1_Token master;
- FT_UInt n;
- FT_Byte* old_cursor;
- FT_Byte* old_limit;
-
-
- if ( !blend || blend->num_designs == 0 )
- {
- FT_ERROR(( "parse_weight_vector: too early!\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- Z1_ToToken( parser, &master );
- if ( master.type != t1_token_array )
- {
- FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
-
- old_cursor = parser->root.cursor;
- old_limit = parser->root.limit;
-
- parser->root.cursor = master.start;
- parser->root.limit = master.limit;
-
- for ( n = 0; n < blend->num_designs; n++ )
- {
- blend->default_weight_vector[n] =
- blend->weight_vector[n] = Z1_ToFixed( parser, 0 );
- }
-
- parser->root.cursor = old_cursor;
- parser->root.limit = old_limit;
-
- Exit:
- parser->root.error = error;
- }
-
-
- /* the keyword `/shareddict' appears in some multiple master fonts */
- /* with a lot of Postscript garbage behind it (that's completely out */
- /* of spec!); we detect it and terminate the parsing */
- /* */
- static
- void parse_shared_dict( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
-
- FT_UNUSED( face );
-
-
- parser->root.cursor = parser->root.limit;
- parser->root.error = 0;
- }
-
-#endif /* Z1_CONFIG_OPTION_NO_MM_SUPPORT */
-
-
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** TYPE 1 SYMBOL PARSING *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* First of all, define the token field static variables. This is a set */
- /* of T1_Field variables used later. */
- /* */
- /*************************************************************************/
-
-
- static
- FT_Error t1_load_keyword( T1_Face face,
- Z1_Loader* loader,
- T1_Field* field )
- {
- FT_Error error;
- void* dummy_object;
- void** objects;
- FT_UInt max_objects;
- T1_Blend* blend = face->blend;
-
-
- /* if the keyword has a dedicated callback, call it */
- if ( field->type == t1_field_callback )
- {
- field->reader( (FT_Face)face, loader );
- error = loader->parser.root.error;
- goto Exit;
- }
-
- /* now, the keyword is either a simple field, or a table of fields; */
- /* we are now going to take care of it */
- switch ( field->location )
- {
- case t1_field_font_info:
- dummy_object = &face->type1.font_info;
- objects = &dummy_object;
- max_objects = 0;
-
- if ( blend )
- {
- objects = (void**)blend->font_infos;
- max_objects = blend->num_designs;
- }
- break;
-
- case t1_field_private:
- dummy_object = &face->type1.private_dict;
- objects = &dummy_object;
- max_objects = 0;
-
- if ( blend )
- {
- objects = (void**)blend->privates;
- max_objects = blend->num_designs;
- }
- break;
-
- default:
- dummy_object = &face->type1;
- objects = &dummy_object;
- max_objects = 0;
- }
-
- if ( field->type == t1_field_integer_array ||
- field->type == t1_field_fixed_array )
- error = Z1_Load_Field_Table( &loader->parser, field,
- objects, max_objects, 0 );
- else
- error = Z1_Load_Field( &loader->parser, field,
- objects, max_objects, 0 );
-
- Exit:
- return error;
- }
-
-
- static
- int is_space( FT_Byte c )
- {
- return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
- }
-
-
- static
- int is_alpha( FT_Byte c )
- {
- return ( isalnum( c ) || c == '.' || c == '_' );
- }
-
-
-
- static
- int read_binary_data( Z1_Parser* parser,
- FT_Int* size,
- FT_Byte** base )
- {
- FT_Byte* cur;
- FT_Byte* limit = parser->root.limit;
-
-
- /* the binary data has the following format */
- /* */
- /* `size' [white*] RD white ....... ND */
- /* */
-
- Z1_Skip_Spaces( parser );
- cur = parser->root.cursor;
-
- if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
- {
- *size = Z1_ToInt( parser );
-
- Z1_Skip_Spaces( parser );
- Z1_Skip_Alpha ( parser ); /* `RD' or `-|' or something else */
-
- /* there is only one whitespace char after the */
- /* `RD' or `-|' token */
- *base = parser->root.cursor + 1;
-
- parser->root.cursor += *size + 1;
- return 1;
- }
-
- FT_ERROR(( "read_binary_data: invalid size field\n" ));
- parser->root.error = T1_Err_Invalid_File_Format;
- return 0;
- }
-
-
- /* we will now define the routines used to handle */
- /* the `/Encoding', `/Subrs', and `/CharStrings' */
- /* dictionaries */
-
- static
- void parse_font_name( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- FT_Error error;
- FT_Memory memory = parser->root.memory;
- FT_Int len;
- FT_Byte* cur;
- FT_Byte* cur2;
- FT_Byte* limit;
-
-
- Z1_Skip_Spaces( parser );
-
- cur = parser->root.cursor;
- limit = parser->root.limit;
-
- if ( cur >= limit - 1 || *cur != '/' )
- return;
-
- cur++;
- cur2 = cur;
- while ( cur2 < limit && is_alpha( *cur2 ) )
- cur2++;
-
- len = cur2 - cur;
- if ( len > 0 )
- {
- if ( ALLOC( face->type1.font_name, len + 1 ) )
- {
- parser->root.error = error;
- return;
- }
-
- MEM_Copy( face->type1.font_name, cur, len );
- face->type1.font_name[len] = '\0';
- }
- parser->root.cursor = cur2;
- }
-
-
- static
- void parse_font_bbox( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- FT_Short temp[4];
- FT_BBox* bbox = &face->type1.font_bbox;
-
-
- (void)Z1_ToCoordArray( parser, 4, temp );
- bbox->xMin = temp[0];
- bbox->yMin = temp[1];
- bbox->xMax = temp[2];
- bbox->yMax = temp[3];
- }
-
-
- static
- void parse_font_matrix( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- FT_Matrix* matrix = &face->type1.font_matrix;
- FT_Vector* offset = &face->type1.font_offset;
- FT_Fixed temp[6];
-
-
- if ( matrix->xx || matrix->yx )
- /* with synthetic fonts, it's possible we get here twice */
- return;
-
- (void)Z1_ToFixedArray( parser, 6, temp, 3 );
-
- /* we need to scale the values by 1.0/temp[3] */
- if ( temp[3] != 0x10000L )
- {
- temp[0] = FT_DivFix( temp[0], temp[3] );
- temp[1] = FT_DivFix( temp[1], temp[3] );
- temp[2] = FT_DivFix( temp[2], temp[3] );
- temp[4] = FT_DivFix( temp[4], temp[3] );
- temp[5] = FT_DivFix( temp[5], temp[3] );
- temp[3] = 0x10000L;
- }
-
- matrix->xx = temp[0];
- matrix->yx = temp[1];
- matrix->xy = temp[2];
- matrix->yy = temp[3];
-
- /* note that the offsets must be expressed in integer font units */
- offset->x = temp[4] >> 16;
- offset->y = temp[5] >> 16;
- }
-
-
- static
- void parse_encoding( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- FT_Byte* cur = parser->root.cursor;
- FT_Byte* limit = parser->root.limit;
-
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
-
-
- /* skip whitespace */
- while ( is_space( *cur ) )
- {
- cur++;
- if ( cur >= limit )
- {
- FT_ERROR(( "parse_encoding: out of bounds!\n" ));
- parser->root.error = T1_Err_Invalid_File_Format;
- return;
- }
- }
-
- /* if we have a number, then the encoding is an array, */
- /* and we must load it now */
- if ( (FT_Byte)( *cur - '0' ) < 10 )
- {
- T1_Encoding* encode = &face->type1.encoding;
- FT_Int count, n;
- PS_Table* char_table = &loader->encoding_table;
- FT_Memory memory = parser->root.memory;
- FT_Error error;
-
-
- /* read the number of entries in the encoding, should be 256 */
- count = Z1_ToInt( parser );
- if ( parser->root.error )
- return;
-
- /* we use a Z1_Table to store our charnames */
- encode->num_chars = count;
- if ( ALLOC_ARRAY( encode->char_index, count, FT_Short ) ||
- ALLOC_ARRAY( encode->char_name, count, FT_String* ) ||
- ( error = psaux->ps_table_funcs->init(
- char_table, count, memory ) ) != 0 )
- {
- parser->root.error = error;
- return;
- }
-
- /* We need to `zero' out encoding_table.elements */
- for ( n = 0; n < count; n++ )
- {
- char* notdef = ".notdef";
-
-
- Z1_Add_Table( char_table, n, notdef, 8 );
- }
-
- /* Now, we will need to read a record of the form */
- /* ... charcode /charname ... for each entry in our table */
- /* */
- /* We simply look for a number followed by an immediate */
- /* name. Note that this ignores correctly the sequence */
- /* that is often seen in type1 fonts: */
- /* */
- /* 0 1 255 { 1 index exch /.notdef put } for dup */
- /* */
- /* used to clean the encoding array before anything else. */
- /* */
- /* We stop when we encounter a `def'. */
-
- cur = parser->root.cursor;
- limit = parser->root.limit;
- n = 0;
-
- for ( ; cur < limit; )
- {
- FT_Byte c;
-
-
- c = *cur;
-
- /* we stop when we encounter a `def' */
- if ( c == 'd' && cur + 3 < limit )
- {
- if ( cur[1] == 'e' &&
- cur[2] == 'f' &&
- is_space(cur[-1]) &&
- is_space(cur[3]) )
- {
- FT_TRACE6(( "encoding end\n" ));
- break;
- }
- }
-
- /* otherwise, we must find a number before anything else */
- if ( (FT_Byte)( c - '0' ) < 10 )
- {
- FT_Int charcode;
-
-
- parser->root.cursor = cur;
- charcode = Z1_ToInt( parser );
- cur = parser->root.cursor;
-
- /* skip whitespace */
- while ( cur < limit && is_space( *cur ) )
- cur++;
-
- if ( cur < limit && *cur == '/' )
- {
- /* bingo, we have an immediate name -- it must be a */
- /* character name */
- FT_Byte* cur2 = cur + 1;
- FT_Int len;
-
-
- while ( cur2 < limit && is_alpha( *cur2 ) )
- cur2++;
-
- len = cur2 - cur - 1;
-
- parser->root.error = Z1_Add_Table( char_table, charcode,
- cur + 1, len + 1 );
- char_table->elements[charcode][len] = '\0';
- if ( parser->root.error )
- return;
-
- cur = cur2;
- }
- }
- else
- cur++;
- }
-
- face->type1.encoding_type = t1_encoding_array;
- parser->root.cursor = cur;
- }
- /* Otherwise, we should have either `StandardEncoding' or */
- /* `ExpertEncoding' */
- else
- {
- if ( cur + 17 < limit &&
- strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
- face->type1.encoding_type = t1_encoding_standard;
-
- else if ( cur + 15 < limit &&
- strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
- face->type1.encoding_type = t1_encoding_expert;
-
- else
- {
- FT_ERROR(( "parse_encoding: invalid token!\n" ));
- parser->root.error = T1_Err_Invalid_File_Format;
- }
- }
- }
-
-
- static
- void parse_subrs( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- PS_Table* table = &loader->subrs;
- FT_Memory memory = parser->root.memory;
- FT_Error error;
- FT_Int n;
-
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
-
-
- loader->num_subrs = Z1_ToInt( parser );
- if ( parser->root.error )
- return;
-
- /* position the parser right before the `dup' of the first subr */
- Z1_Skip_Spaces( parser );
- Z1_Skip_Alpha( parser ); /* `array' */
- Z1_Skip_Spaces( parser );
-
- /* initialize subrs array */
- error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
- if ( error )
- goto Fail;
-
- /* the format is simple: */
- /* */
- /* `index' + binary data */
- /* */
-
- for ( n = 0; n < loader->num_subrs; n++ )
- {
- FT_Int index, size;
- FT_Byte* base;
-
-
- /* If the next token isn't `dup', we are also done. This */
- /* happens when there are `holes' in the Subrs array. */
- if ( strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
- break;
-
- index = Z1_ToInt( parser );
-
- if ( !read_binary_data( parser, &size, &base ) )
- return;
-
- /* The binary string is followed by one token, e.g. `NP' */
- /* (bound to `noaccess put') or by two separate tokens: */
- /* `noaccess' & `put'. We position the parser right */
- /* before the next `dup', if any. */
- Z1_Skip_Spaces( parser );
- Z1_Skip_Alpha( parser ); /* `NP' or `I' or `noaccess' */
- Z1_Skip_Spaces( parser );
-
- if ( strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
- {
- Z1_Skip_Alpha( parser ); /* skip `put' */
- Z1_Skip_Spaces( parser );
- }
-
- /* some fonts use a value of -1 for lenIV to indicate that */
- /* the charstrings are unencoded */
- /* */
- /* thanks to Tom Kacvinsky for pointing this out */
- /* */
- if ( face->type1.private_dict.lenIV >= 0 )
- {
- Z1_Decrypt( base, size, 4330 );
- size -= face->type1.private_dict.lenIV;
- base += face->type1.private_dict.lenIV;
- }
-
- error = Z1_Add_Table( table, index, base, size );
- if ( error )
- goto Fail;
- }
- return;
-
- Fail:
- parser->root.error = error;
- }
-
-
- static
- void parse_charstrings( T1_Face face,
- Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
- PS_Table* code_table = &loader->charstrings;
- PS_Table* name_table = &loader->glyph_names;
- FT_Memory memory = parser->root.memory;
- FT_Error error;
-
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
-
- FT_Byte* cur;
- FT_Byte* limit = parser->root.limit;
- FT_Int n;
- FT_UInt notdef_index = 0;
- FT_Byte notdef_found = 0;
-
-
- if ( loader->num_glyphs )
- /* with synthetic fonts, it's possible we get here twice */
- return;
-
- loader->num_glyphs = Z1_ToInt( parser );
- if ( parser->root.error )
- return;
-
- /* initialize tables, adding space for `swap' at table end */
- error = psaux->ps_table_funcs->init( code_table,
- loader->num_glyphs + 1,
- memory );
- if ( error )
- goto Fail;
-
- error = psaux->ps_table_funcs->init( name_table,
- loader->num_glyphs + 1,
- memory );
- if ( error )
- goto Fail;
-
- n = 0;
- for (;;)
- {
- FT_Int size;
- FT_Byte* base;
-
-
- /* the format is simple: */
- /* `/glyphname' + binary data */
- /* */
- /* note that we stop when we find a `def' */
- /* */
- Z1_Skip_Spaces( parser );
-
- cur = parser->root.cursor;
- if ( cur >= limit )
- break;
-
- /* we stop when we find a `def' or `end' keyword */
- if ( *cur == 'd' &&
- cur + 3 < limit &&
- cur[1] == 'e' &&
- cur[2] == 'f' )
- break;
-
- if ( *cur == 'e' &&
- cur + 3 < limit &&
- cur[1] == 'n' &&
- cur[2] == 'd' )
- break;
-
- if ( *cur != '/' )
- Z1_Skip_Alpha( parser );
- else
- {
- FT_Byte* cur2 = cur + 1;
- FT_Int len;
-
-
- while ( cur2 < limit && is_alpha( *cur2 ) )
- cur2++;
- len = cur2 - cur - 1;
-
- error = Z1_Add_Table( name_table, n, cur + 1, len + 1 );
- if ( error )
- goto Fail;
-
- /* add a trailing zero to the name table */
- name_table->elements[n][len] = '\0';
-
- /* record index of /.notdef */
- if ( strcmp( (const char*)".notdef",
- (const char*)(name_table->elements[n]) ) == 0 )
- {
- notdef_index = n;
- notdef_found = 1;
- }
-
- parser->root.cursor = cur2;
- if ( !read_binary_data( parser, &size, &base ) )
- return;
-
- if ( face->type1.private_dict.lenIV >= 0 )
- {
- Z1_Decrypt( base, size, 4330 );
- size -= face->type1.private_dict.lenIV;
- base += face->type1.private_dict.lenIV;
- }
-
- error = Z1_Add_Table( code_table, n, base, size );
- if ( error )
- goto Fail;
-
- n++;
- if ( n >= loader->num_glyphs )
- break;
- }
- }
-
- loader->num_glyphs = n;
-
- /* if /.notdef is found but does not occupy index 0, do our magic. */
- if ( strcmp( (const char*)".notdef",
- (const char*)name_table->elements[0] ) &&
- notdef_found )
- {
-
- /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
- /* name/code to end of table. Then place notdef_index name/code into */
- /* index 0. Then take end of table name/code and place it into index */
- /* notdef_index. */
-
- error = Z1_Add_Table( name_table, n,
- name_table->elements[0],
- name_table->lengths [0] );
- if ( error )
- goto Fail;
- error = Z1_Add_Table( code_table, n,
- code_table->elements[0],
- code_table->lengths [0] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( name_table, 0,
- name_table->elements[notdef_index],
- name_table->lengths [notdef_index] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( code_table, 0,
- code_table->elements[notdef_index],
- code_table->lengths [notdef_index] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( name_table, notdef_index,
- name_table->elements[n],
- name_table->lengths [n] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( code_table, notdef_index,
- code_table->elements[n],
- code_table->lengths [n] );
- if ( error )
- goto Fail;
-
- }
- else if ( !notdef_found )
- {
-
- /* notdef_index is already 0, or /.notdef is undefined in */
- /* charstrings dictionary. Worry about /.notdef undefined. */
- /* we take index 0 and add it to the end of the table(s) */
- /* and add our own /.notdef glyph to index 0. */
-
- /* 0 333 hsbw endchar */
- FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
- char* notdef_name = ".notdef";
-
-
- error = Z1_Add_Table( name_table, n,
- name_table->elements[0],
- name_table->lengths [0] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( code_table, n,
- code_table->elements[0],
- code_table->lengths [0] );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( name_table, 0, notdef_name, 8 );
- if ( error )
- goto Fail;
-
- error = Z1_Add_Table( code_table, 0, notdef_glyph, 5 );
-
- if ( error )
- goto Fail;
-
- /* we added a glyph. */
- loader->num_glyphs = n + 1;
-
- }
-
- return;
-
- Fail:
- parser->root.error = error;
- }
-
-
- static
- const T1_Field t1_keywords[] =
- {
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1tokens.h"
-
-#else
-
-#include <type1/z1tokens.h>
-
-#endif
-
- /* now add the special functions... */
- T1_FIELD_CALLBACK( "FontName", parse_font_name )
- T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
- T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
- T1_FIELD_CALLBACK( "Encoding", parse_encoding )
- T1_FIELD_CALLBACK( "Subrs", parse_subrs )
- T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
- T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
- T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
- T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
- T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
- T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
-#endif
-
- { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
- };
-
-
- static
- FT_Error parse_dict( T1_Face face,
- Z1_Loader* loader,
- FT_Byte* base,
- FT_Long size )
- {
- Z1_Parser* parser = &loader->parser;
-
-
- parser->root.cursor = base;
- parser->root.limit = base + size;
- parser->root.error = 0;
-
- {
- FT_Byte* cur = base;
- FT_Byte* limit = cur + size;
-
-
- for ( ; cur < limit; cur++ )
- {
- /* look for `FontDirectory', which causes problems on some fonts */
- if ( *cur == 'F' && cur + 25 < limit &&
- strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
- {
- FT_Byte* cur2;
-
-
- /* skip the `FontDirectory' keyword */
- cur += 13;
- cur2 = cur;
-
- /* lookup the `known' keyword */
- while ( cur < limit && *cur != 'k' &&
- strncmp( (char*)cur, "known", 5 ) )
- cur++;
-
- if ( cur < limit )
- {
- T1_Token token;
-
-
- /* skip the `known' keyword and the token following it */
- cur += 5;
- loader->parser.root.cursor = cur;
- Z1_ToToken( &loader->parser, &token );
-
- /* if the last token was an array, skip it! */
- if ( token.type == t1_token_array )
- cur2 = parser->root.cursor;
- }
- cur = cur2;
- }
- /* look for immediates */
- else if ( *cur == '/' && cur + 2 < limit )
- {
- FT_Byte* cur2;
- FT_Int len;
-
-
- cur++;
- cur2 = cur;
- while ( cur2 < limit && is_alpha( *cur2 ) )
- cur2++;
-
- len = cur2 - cur;
- if ( len > 0 && len < 22 )
- {
- if ( !loader->fontdata )
- {
- if ( strncmp( (char*)cur, "FontInfo", 8 ) == 0 )
- loader->fontdata = 1;
- }
- else
- {
- /* now, compare the immediate name to the keyword table */
- T1_Field* keyword = (T1_Field*)t1_keywords;
-
-
- for (;;)
- {
- FT_Byte* name;
-
-
- name = (FT_Byte*)keyword->ident;
- if ( !name )
- break;
-
- if ( cur[0] == name[0] &&
- len == (FT_Int)strlen( (const char*)name ) )
- {
- FT_Int n;
-
-
- for ( n = 1; n < len; n++ )
- if ( cur[n] != name[n] )
- break;
-
- if ( n >= len )
- {
- /* we found it -- run the parsing callback! */
- parser->root.cursor = cur2;
- Z1_Skip_Spaces( parser );
- parser->root.error = t1_load_keyword( face,
- loader,
- keyword );
- if ( parser->root.error )
- return parser->root.error;
-
- cur = parser->root.cursor;
- break;
- }
- }
- keyword++;
- }
- }
- }
- }
- }
- }
- return parser->root.error;
- }
-
-
- static
- void t1_init_loader( Z1_Loader* loader,
- T1_Face face )
- {
- FT_UNUSED( face );
-
- MEM_Set( loader, 0, sizeof ( *loader ) );
- loader->num_glyphs = 0;
- loader->num_chars = 0;
-
- /* initialize the tables -- simply set their `init' field to 0 */
- loader->encoding_table.init = 0;
- loader->charstrings.init = 0;
- loader->glyph_names.init = 0;
- loader->subrs.init = 0;
- loader->fontdata = 0;
- }
-
-
- static
- void t1_done_loader( Z1_Loader* loader )
- {
- Z1_Parser* parser = &loader->parser;
-
-
- /* finalize tables */
- Z1_Release_Table( &loader->encoding_table );
- Z1_Release_Table( &loader->charstrings );
- Z1_Release_Table( &loader->glyph_names );
- Z1_Release_Table( &loader->subrs );
-
- /* finalize parser */
- Z1_Done_Parser( parser );
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Open_Face( T1_Face face )
- {
- Z1_Loader loader;
- Z1_Parser* parser;
- T1_Font* type1 = &face->type1;
- FT_Error error;
-
- PSAux_Interface* psaux = (PSAux_Interface*)face->psaux;
-
-
- t1_init_loader( &loader, face );
-
- /* default lenIV */
- type1->private_dict.lenIV = 4;
-
- parser = &loader.parser;
- error = Z1_New_Parser( parser,
- face->root.stream,
- face->root.memory,
- psaux );
- if ( error )
- goto Exit;
-
- error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
- if ( error )
- goto Exit;
-
- error = Z1_Get_Private_Dict( parser );
- if ( error )
- goto Exit;
-
- error = parse_dict( face, &loader, parser->private_dict,
- parser->private_len );
- if ( error )
- goto Exit;
-
- /* now, propagate the subrs, charstrings, and glyphnames tables */
- /* to the Type1 data */
- type1->num_glyphs = loader.num_glyphs;
-
- if ( !loader.subrs.init )
- {
- FT_ERROR(( "Z1_Open_Face: no subrs array in face!\n" ));
- error = T1_Err_Invalid_File_Format;
- }
-
- if ( !loader.charstrings.init )
- {
- FT_ERROR(( "Z1_Open_Face: no charstrings array in face!\n" ));
- error = T1_Err_Invalid_File_Format;
- }
-
- loader.subrs.init = 0;
- type1->num_subrs = loader.num_subrs;
- type1->subrs_block = loader.subrs.block;
- type1->subrs = loader.subrs.elements;
- type1->subrs_len = loader.subrs.lengths;
-
- loader.charstrings.init = 0;
- type1->charstrings_block = loader.charstrings.block;
- type1->charstrings = loader.charstrings.elements;
- type1->charstrings_len = loader.charstrings.lengths;
-
- /* we copy the glyph names `block' and `elements' fields; */
- /* the `lengths' field must be released later */
- type1->glyph_names_block = loader.glyph_names.block;
- type1->glyph_names = (FT_String**)loader.glyph_names.elements;
- loader.glyph_names.block = 0;
- loader.glyph_names.elements = 0;
-
- /* we must now build type1.encoding when we have a custom */
- /* array.. */
- if ( type1->encoding_type == t1_encoding_array )
- {
- FT_Int charcode, index, min_char, max_char;
- FT_Byte* char_name;
- FT_Byte* glyph_name;
-
-
- /* OK, we do the following: for each element in the encoding */
- /* table, look up the index of the glyph having the same name */
- /* the index is then stored in type1.encoding.char_index, and */
- /* a the name to type1.encoding.char_name */
-
- min_char = +32000;
- max_char = -32000;
-
- charcode = 0;
- for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
- {
- type1->encoding.char_index[charcode] = 0;
- type1->encoding.char_name [charcode] = (char *)".notdef";
-
- char_name = loader.encoding_table.elements[charcode];
- if ( char_name )
- for ( index = 0; index < type1->num_glyphs; index++ )
- {
- glyph_name = (FT_Byte*)type1->glyph_names[index];
- if ( strcmp( (const char*)char_name,
- (const char*)glyph_name ) == 0 )
- {
- type1->encoding.char_index[charcode] = index;
- type1->encoding.char_name [charcode] = (char*)glyph_name;
-
- /* Change min/max encoded char only if glyph name is */
- /* not /.notdef */
- if ( strcmp( (const char*)".notdef",
- (const char*)glyph_name ) != 0 )
- {
- if (charcode < min_char) min_char = charcode;
- if (charcode > max_char) max_char = charcode;
- }
- break;
- }
- }
- }
- type1->encoding.code_first = min_char;
- type1->encoding.code_last = max_char;
- type1->encoding.num_chars = loader.num_chars;
- }
-
- Exit:
- t1_done_loader( &loader );
- return error;
- }
-
-
-/* END */
--- a/src/type1/z1load.h
+++ /dev/null
@@ -1,93 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1load.h */
-/* */
-/* Experimental Type 1 font 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. */
-/* */
-/***************************************************************************/
-
-
-#ifndef Z1LOAD_H
-#define Z1LOAD_H
-
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/psaux.h>
-#include <freetype/ftmm.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1parse.h"
-
-#else
-
-#include <type1/z1parse.h>
-
-#endif
-
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- typedef struct Z1_Loader_
- {
- Z1_Parser parser; /* parser used to read the stream */
-
- FT_Int num_chars; /* number of characters in encoding */
- PS_Table encoding_table; /* PS_Table used to store the */
- /* encoding character names */
-
- FT_Int num_glyphs;
- PS_Table glyph_names;
- PS_Table charstrings;
-
- FT_Int num_subrs;
- PS_Table subrs;
- FT_Bool fontdata;
-
- } Z1_Loader;
-
-
- LOCAL_DEF
- FT_Error Z1_Open_Face( T1_Face face );
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
-
- LOCAL_DEF
- FT_Error Z1_Get_Multi_Master( T1_Face face,
- FT_Multi_Master* master );
-
- LOCAL_DEF
- FT_Error Z1_Set_MM_Blend( T1_Face face,
- FT_UInt num_coords,
- FT_Fixed* coords );
-
- LOCAL_DEF
- FT_Error Z1_Set_MM_Design( T1_Face face,
- FT_UInt num_coords,
- FT_Long* coords );
-
- LOCAL_DEF
- void Z1_Done_Blend( T1_Face face );
-
-#endif /* !Z1_CONFIG_OPTION_NO_MM_SUPPORT */
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* Z1LOAD_H */
-
-
-/* END */
--- a/src/type1/z1objs.c
+++ /dev/null
@@ -1,406 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1objs.c */
-/* */
-/* Experimental Type 1 objects manager (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. */
-/* */
-/***************************************************************************/
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftstream.h>
-
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1gload.h"
-#include "z1load.h"
-#include "z1afm.h"
-
-#else
-
-#include <type1/z1gload.h>
-#include <type1/z1load.h>
-#include <type1/z1afm.h>
-
-#endif
-
-
-#include <freetype/internal/psnames.h>
-#include <freetype/internal/psaux.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_z1objs
-
-
- /*************************************************************************/
- /* */
- /* FACE FUNCTIONS */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Z1_Done_Face */
- /* */
- /* <Description> */
- /* The face object destructor. */
- /* */
- /* <Input> */
- /* face :: A typeless pointer to the face object to destroy. */
- /* */
- LOCAL_FUNC
- void Z1_Done_Face( T1_Face face )
- {
- FT_Memory memory;
- T1_Font* type1 = &face->type1;
-
-
- if ( face )
- {
- memory = face->root.memory;
-
-#ifndef Z1_CONFIG_OPTION_NO_MM_SUPPORT
- /* release multiple masters information */
- Z1_Done_Blend( face );
- face->blend = 0;
-#endif
-
- /* release font info strings */
- {
- T1_FontInfo* info = &type1->font_info;
-
-
- FREE( info->version );
- FREE( info->notice );
- FREE( info->full_name );
- FREE( info->family_name );
- FREE( info->weight );
- }
-
- /* release top dictionary */
- FREE( type1->charstrings_len );
- FREE( type1->charstrings );
- FREE( type1->glyph_names );
-
- FREE( type1->subrs );
- FREE( type1->subrs_len );
-
- FREE( type1->subrs_block );
- FREE( type1->charstrings_block );
- FREE( type1->glyph_names_block );
-
- FREE( type1->encoding.char_index );
- FREE( type1->font_name );
-
-#ifndef Z1_CONFIG_OPTION_NO_AFM
- /* release afm data if present */
- if ( face->afm_data )
- Z1_Done_AFM( memory, (Z1_AFM*)face->afm_data );
-#endif
-
- /* release unicode map, if any */
- FREE( face->unicode_map.maps );
- face->unicode_map.num_maps = 0;
-
- face->root.family_name = 0;
- face->root.style_name = 0;
- }
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Z1_Init_Face */
- /* */
- /* <Description> */
- /* The face object constructor. */
- /* */
- /* <Input> */
- /* stream :: input stream where to load font data. */
- /* */
- /* face_index :: The index of the font face in the resource. */
- /* */
- /* num_params :: Number of additional generic parameters. Ignored. */
- /* */
- /* params :: Additional generic parameters. Ignored. */
- /* */
- /* <InOut> */
- /* face :: The face record to build. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error Z1_Init_Face( FT_Stream stream,
- T1_Face face,
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params )
- {
- FT_Error error;
- PSNames_Interface* psnames;
- PSAux_Interface* psaux;
-
- FT_UNUSED( num_params );
- FT_UNUSED( params );
- FT_UNUSED( face_index );
- FT_UNUSED( stream );
-
-
- face->root.num_faces = 1;
-
- psnames = (PSNames_Interface*)face->psnames;
- if ( !psnames )
- {
- psnames = (PSNames_Interface*)
- FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psnames" );
-
- face->psnames = psnames;
- }
-
- psaux = (PSAux_Interface*)face->psaux;
- if ( !psaux )
- {
- psaux = (PSAux_Interface*)
- FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), "psaux" );
-
- face->psaux = psaux;
- }
-
- /* open the tokenizer, this will also check the font format */
- error = Z1_Open_Face( face );
- if ( error )
- goto Exit;
-
- /* if we just wanted to check the format, leave successfully now */
- if ( face_index < 0 )
- goto Exit;
-
- /* check the face index */
- if ( face_index != 0 )
- {
- FT_ERROR(( "Z1_Init_Face: invalid face index\n" ));
- error = T1_Err_Invalid_Argument;
- goto Exit;
- }
-
- /* Now, load the font program into the face object */
-
- /* Init the face object fields */
- /* Now set up root face fields */
- {
- FT_Face root = (FT_Face)&face->root;
-
-
- root->num_glyphs = face->type1.num_glyphs;
- root->num_charmaps = 1;
-
- root->face_index = face_index;
- root->face_flags = FT_FACE_FLAG_SCALABLE;
-
- root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
-
- root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
-
- if ( face->type1.font_info.is_fixed_pitch )
- root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
-
- if ( face->blend )
- root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
-
- /* XXX: TODO -- add kerning with .afm support */
-
- /* get style name -- be careful, some broken fonts only */
- /* have a `/FontName' dictionary entry! */
- root->family_name = face->type1.font_info.family_name;
- if ( root->family_name )
- {
- char* full = face->type1.font_info.full_name;
- char* family = root->family_name;
-
-
- while ( *family && *full == *family )
- {
- family++;
- full++;
- }
-
- root->style_name = ( *full == ' ' ? full + 1
- : (char *)"Regular" );
- }
- else
- {
- /* do we have a `/FontName'? */
- if ( face->type1.font_name )
- {
- root->family_name = face->type1.font_name;
- root->style_name = (char *)"Regular";
- }
- }
-
- /* no embedded bitmap support */
- root->num_fixed_sizes = 0;
- root->available_sizes = 0;
-
- root->bbox = face->type1.font_bbox;
- root->units_per_EM = 1000;
- root->ascender = (FT_Short)face->type1.font_bbox.yMax;
- root->descender = (FT_Short)face->type1.font_bbox.yMin;
- root->height = ( ( root->ascender + root->descender ) * 12 ) / 10;
-
- /* now compute the maximum advance width */
-
- root->max_advance_width = face->type1.private_dict.standard_width[0];
-
- /* compute max advance width for proportional fonts */
- if ( !face->type1.font_info.is_fixed_pitch )
- {
- FT_Int max_advance;
-
-
- error = Z1_Compute_Max_Advance( face, &max_advance );
-
- /* in case of error, keep the standard width */
- if ( !error )
- root->max_advance_width = max_advance;
- else
- error = 0; /* clear error */
- }
-
- root->max_advance_height = root->height;
-
- root->underline_position = face->type1.font_info.underline_position;
- root->underline_thickness = face->type1.font_info.underline_thickness;
-
- root->max_points = 0;
- root->max_contours = 0;
- }
-
- /* charmap support -- synthetize unicode charmap if possible */
- {
- FT_Face root = &face->root;
- FT_CharMap charmap = face->charmaprecs;
-
-
- /* synthesize a Unicode charmap if there is support in the `PSNames' */
- /* module */
- if ( psnames )
- {
- if ( psnames->unicode_value )
- {
- error = psnames->build_unicodes(
- root->memory,
- face->type1.num_glyphs,
- (const char**)face->type1.glyph_names,
- &face->unicode_map );
- if ( !error )
- {
- root->charmap = charmap;
- charmap->face = (FT_Face)face;
- charmap->encoding = ft_encoding_unicode;
- charmap->platform_id = 3;
- charmap->encoding_id = 1;
- charmap++;
- }
-
- /* simply clear the error in case of failure (which really) */
- /* means that out of memory or no unicode glyph names */
- error = FT_Err_Ok;
- }
- }
-
- /* now, support either the standard, expert, or custom encoding */
- charmap->face = (FT_Face)face;
- charmap->platform_id = 7; /* a new platform id for Adobe fonts? */
-
- switch ( face->type1.encoding_type )
- {
- case t1_encoding_standard:
- charmap->encoding = ft_encoding_adobe_standard;
- charmap->encoding_id = 0;
- break;
-
- case t1_encoding_expert:
- charmap->encoding = ft_encoding_adobe_expert;
- charmap->encoding_id = 1;
- break;
-
- default:
- charmap->encoding = ft_encoding_adobe_custom;
- charmap->encoding_id = 2;
- break;
- }
-
- root->charmaps = face->charmaps;
- root->num_charmaps = charmap - face->charmaprecs + 1;
- face->charmaps[0] = &face->charmaprecs[0];
- face->charmaps[1] = &face->charmaprecs[1];
- }
-
- Exit:
- return error;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Z1_Init_Driver */
- /* */
- /* <Description> */
- /* Initializes a given Type 1 driver object. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target driver object. */
- /* */
- /* <Return> */
- /* FreeType error code. 0 means success. */
- /* */
- LOCAL_FUNC
- FT_Error Z1_Init_Driver( Z1_Driver driver )
- {
- FT_UNUSED( driver );
-
- return T1_Err_Ok;
- }
-
-
- /*************************************************************************/
- /* */
- /* <Function> */
- /* Z1_Done_Driver */
- /* */
- /* <Description> */
- /* Finalizes a given Type 1 driver. */
- /* */
- /* <Input> */
- /* driver :: A handle to the target Type 1 driver. */
- /* */
- LOCAL_DEF
- void Z1_Done_Driver( Z1_Driver driver )
- {
- FT_UNUSED( driver );
- }
-
-
-/* END */
--- a/src/type1/z1objs.h
+++ /dev/null
@@ -1,161 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1objs.h */
-/* */
-/* Experimental Type 1 objects manager (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 Z1OBJS_H
-#define Z1OBJS_H
-
-#include <freetype/internal/ftobjs.h>
-#include <freetype/config/ftconfig.h>
-#include <freetype/internal/t1errors.h>
-#include <freetype/internal/t1types.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- /* The following structures must be defined by the hinter */
- typedef struct Z1_Size_Hints_ Z1_Size_Hints;
- typedef struct Z1_Glyph_Hints_ Z1_Glyph_Hints;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_Driver */
- /* */
- /* <Description> */
- /* A handle to a Type 1 driver object. */
- /* */
- typedef struct Z1_DriverRec_ *Z1_Driver;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_Size */
- /* */
- /* <Description> */
- /* A handle to a Type 1 size object. */
- /* */
- typedef struct Z1_SizeRec_* Z1_Size;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_GlyphSlot */
- /* */
- /* <Description> */
- /* A handle to a Type 1 glyph slot object. */
- /* */
- typedef struct Z1_GlyphSlotRec_* Z1_GlyphSlot;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_CharMap */
- /* */
- /* <Description> */
- /* A handle to a Type 1 character mapping object. */
- /* */
- /* <Note> */
- /* The Type 1 format doesn't use a charmap but an encoding table. */
- /* The driver is responsible for making up charmap objects */
- /* corresponding to these tables. */
- /* */
- typedef struct Z1_CharMapRec_* Z1_CharMap;
-
-
- /*************************************************************************/
- /* */
- /* HERE BEGINS THE TYPE1 SPECIFIC STUFF */
- /* */
- /*************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_SizeRec */
- /* */
- /* <Description> */
- /* Type 1 size record. */
- /* */
- typedef struct Z1_SizeRec_
- {
- FT_SizeRec root;
- FT_Bool valid;
- Z1_Size_Hints* hints; /* defined in the hinter. This allows */
- /* us to experiment with different */
- /* hinting schemes without having to */
- /* change `z1objs' each time. */
- } Z1_SizeRec;
-
-
- /*************************************************************************/
- /* */
- /* <Type> */
- /* Z1_GlyphSlotRec */
- /* */
- /* <Description> */
- /* Type 1 glyph slot record. */
- /* */
- typedef struct Z1_GlyphSlotRec_
- {
- FT_GlyphSlotRec root;
-
- FT_Bool hint;
- FT_Bool scaled;
-
- FT_Int max_points;
- FT_Int max_contours;
-
- FT_Fixed x_scale;
- FT_Fixed y_scale;
-
- Z1_Glyph_Hints* hints; /* defined in the hinter */
-
- } Z1_GlyphSlotRec;
-
-
- LOCAL_DEF
- FT_Error Z1_Init_Face( FT_Stream stream,
- T1_Face face,
- FT_Int face_index,
- FT_Int num_params,
- FT_Parameter* params );
-
- LOCAL_DEF
- void Z1_Done_Face( T1_Face face );
-
- LOCAL_DEF
- FT_Error Z1_Init_Driver( Z1_Driver driver );
-
- LOCAL_DEF
- void Z1_Done_Driver( Z1_Driver driver );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* Z1OBJS_H */
-
-
-/* END */
--- a/src/type1/z1parse.c
+++ /dev/null
@@ -1,487 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1parse.c */
-/* */
-/* Experimental Type 1 parser (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. */
-/* */
-/***************************************************************************/
-
-
- /*************************************************************************/
- /* */
- /* The Type 1 parser is in charge of the following: */
- /* */
- /* - provide an implementation of a growing sequence of objects called */
- /* a `Z1_Table' (used to build various tables needed by the loader). */
- /* */
- /* - opening .pfb and .pfa files to extract their top-level and private */
- /* dictionaries. */
- /* */
- /* - read numbers, arrays & strings from any dictionary. */
- /* */
- /* See `z1load.c' to see how data is loaded from the font file. */
- /* */
- /*************************************************************************/
-
-
-#include <freetype/internal/ftdebug.h>
-#include <freetype/internal/ftcalc.h>
-#include <freetype/internal/ftobjs.h>
-#include <freetype/internal/ftstream.h>
-#include <freetype/internal/t1errors.h>
-#include <freetype/internal/psaux.h>
-
-#ifdef FT_FLAT_COMPILE
-
-#include "z1parse.h"
-
-#else
-
-#include <type1/z1parse.h>
-
-#endif
-
-
-#include <string.h> /* for strncmp() */
-
-
- /*************************************************************************/
- /* */
- /* 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_z1parse
-
-
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
- /***** *****/
- /***** INPUT STREAM PARSER *****/
- /***** *****/
- /*************************************************************************/
- /*************************************************************************/
- /*************************************************************************/
-
-
-#define IS_Z1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
-#define IS_Z1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
-
-#define IS_Z1_SPACE( c ) ( IS_Z1_WHITESPACE( c ) || IS_Z1_LINESPACE( c ) )
-
-
- typedef struct PFB_Tag_
- {
- FT_UShort tag;
- FT_Long size;
-
- } PFB_Tag;
-
-
-#undef FT_STRUCTURE
-#define FT_STRUCTURE PFB_Tag
-
-
- static
- const FT_Frame_Field pfb_tag_fields[] =
- {
- FT_FRAME_START( 6 ),
- FT_FRAME_USHORT ( tag ),
- FT_FRAME_LONG_LE( size ),
- FT_FRAME_END
- };
-
-
- static
- FT_Error read_pfb_tag( FT_Stream stream,
- FT_UShort* tag,
- FT_Long* size )
- {
- FT_Error error;
- PFB_Tag head;
-
-
- *tag = 0;
- *size = 0;
- if ( !READ_Fields( pfb_tag_fields, &head ) )
- {
- if ( head.tag == 0x8001 || head.tag == 0x8002 )
- {
- *tag = head.tag;
- *size = head.size;
- }
- }
- return error;
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_New_Parser( Z1_Parser* parser,
- FT_Stream stream,
- FT_Memory memory,
- PSAux_Interface* psaux )
- {
- FT_Error error;
- FT_UShort tag;
- FT_Long size;
-
-
- psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
-
- parser->stream = stream;
- parser->base_len = 0;
- parser->base_dict = 0;
- parser->private_len = 0;
- parser->private_dict = 0;
- parser->in_pfb = 0;
- parser->in_memory = 0;
- parser->single_block = 0;
-
- /******************************************************************/
- /* */
- /* Here a short summary of what is going on: */
- /* */
- /* When creating a new Type 1 parser, we try to locate and load */
- /* the base dictionary if this is possible (i.e. for PFB */
- /* files). Otherwise, we load the whole font into memory. */
- /* */
- /* When `loading' the base dictionary, we only setup pointers */
- /* in the case of a memory-based stream. Otherwise, we */
- /* allocate and load the base dictionary in it. */
- /* */
- /* parser->in_pfb is set if we are in a binary (".pfb") font. */
- /* parser->in_memory is set if we have a memory stream. */
- /* */
-
- /* try to compute the size of the base dictionary; */
- /* look for a Postscript binary file tag, i.e 0x8001 */
- if ( FILE_Seek( 0L ) )
- goto Exit;
-
- error = read_pfb_tag( stream, &tag, &size );
- if ( error )
- goto Exit;
-
- if ( tag != 0x8001 )
- {
- /* assume that this is a PFA file for now; an error will */
- /* be produced later when more things are checked */
- if ( FILE_Seek( 0L ) )
- goto Exit;
- size = stream->size;
- }
- else
- parser->in_pfb = 1;
-
- /* now, try to load `size' bytes of the `base' dictionary we */
- /* found previously */
-
- /* if it is a memory-based resource, set up pointers */
- if ( !stream->read )
- {
- parser->base_dict = (FT_Byte*)stream->base + stream->pos;
- parser->base_len = size;
- parser->in_memory = 1;
-
- /* check that the `size' field is valid */
- if ( FILE_Skip( size ) )
- goto Exit;
- }
- else
- {
- /* read segment in memory */
- if ( ALLOC( parser->base_dict, size ) ||
- FILE_Read( parser->base_dict, size ) )
- goto Exit;
- parser->base_len = size;
- }
-
- /* Now check font format; we must see `%!PS-AdobeFont-1' */
- /* or `%!FontType' */
- {
- if ( size <= 16 ||
- ( strncmp( (const char*)parser->base_dict,
- "%!PS-AdobeFont-1", 16 ) &&
- strncmp( (const char*)parser->base_dict,
- "%!FontType", 10 ) ) )
- {
- FT_TRACE2(( "[not a Type1 font]\n" ));
- error = FT_Err_Unknown_File_Format;
- }
- else
- {
- parser->root.base = parser->base_dict;
- parser->root.cursor = parser->base_dict;
- parser->root.limit = parser->root.cursor + parser->base_len;
- }
- }
-
- Exit:
- if ( error && !parser->in_memory )
- FREE( parser->base_dict );
-
- return error;
- }
-
-
- LOCAL_FUNC
- void Z1_Done_Parser( Z1_Parser* parser )
- {
- FT_Memory memory = parser->root.memory;
-
-
- /* always free the private dictionary */
- FREE( parser->private_dict );
-
- /* free the base dictionary only when we have a disk stream */
- if ( !parser->in_memory )
- FREE( parser->base_dict );
-
- parser->root.funcs.done( &parser->root );
- }
-
-
- /* return the value of an hexadecimal digit */
- static
- int hexa_value( char c )
- {
- unsigned int d;
-
-
- d = (unsigned int)( c - '0' );
- if ( d <= 9 )
- return (int)d;
-
- d = (unsigned int)( c - 'a' );
- if ( d <= 5 )
- return (int)( d + 10 );
-
- d = (unsigned int)( c - 'A' );
- if ( d <= 5 )
- return (int)( d + 10 );
-
- return -1;
- }
-
-
- LOCAL_FUNC
- void Z1_Decrypt( FT_Byte* buffer,
- FT_Int length,
- FT_UShort seed )
- {
- while ( length > 0 )
- {
- FT_Byte plain;
-
-
- plain = ( *buffer ^ ( seed >> 8 ) );
- seed = ( *buffer + seed ) * 52845 + 22719;
- *buffer++ = plain;
- length--;
- }
- }
-
-
- LOCAL_FUNC
- FT_Error Z1_Get_Private_Dict( Z1_Parser* parser )
- {
- FT_Stream stream = parser->stream;
- FT_Memory memory = parser->root.memory;
- FT_Error error = 0;
- FT_Long size;
-
-
- if ( parser->in_pfb )
- {
- /* in the case of the PFB format, the private dictionary can be */
- /* made of several segments. We thus first read the number of */
- /* segments to compute the total size of the private dictionary */
- /* then re-read them into memory. */
- FT_Long start_pos = FILE_Pos();
- FT_UShort tag;
-
-
- parser->private_len = 0;
- for (;;)
- {
- error = read_pfb_tag( stream, &tag, &size );
- if ( error )
- goto Fail;
-
- if ( tag != 0x8002 )
- break;
-
- parser->private_len += size;
-
- if ( FILE_Skip( size ) )
- goto Fail;
- }
-
- /* Check that we have a private dictionary there */
- /* and allocate private dictionary buffer */
- if ( parser->private_len == 0 )
- {
- FT_ERROR(( "Z1_Get_Private_Dict:" ));
- FT_ERROR(( " invalid private dictionary section\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Fail;
- }
-
- if ( FILE_Seek( start_pos ) ||
- ALLOC( parser->private_dict, parser->private_len ) )
- goto Fail;
-
- parser->private_len = 0;
- for (;;)
- {
- error = read_pfb_tag( stream, &tag, &size );
- if ( error || tag != 0x8002 )
- {
- error = FT_Err_Ok;
- break;
- }
-
- if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
- goto Fail;
-
- parser->private_len += size;
- }
- }
- else
- {
- /* we have already `loaded' the whole PFA font file into memory; */
- /* if this is a memory resource, allocate a new block to hold */
- /* the private dict. Otherwise, simply overwrite into the base */
- /* dictionary block in the heap. */
-
- /* first of all, look at the `eexec' keyword */
- FT_Byte* cur = parser->base_dict;
- FT_Byte* limit = cur + parser->base_len;
- FT_Byte c;
-
-
- for (;;)
- {
- c = cur[0];
- if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
- /* newline + 4 chars */
- {
- if ( cur[1] == 'e' && cur[2] == 'x' &&
- cur[3] == 'e' && cur[4] == 'c' )
- {
- cur += 6; /* we skip the newling after the `eexec' */
-
- /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
- /* skip the extra \n if we find it */
- if ( cur[0] == '\n' )
- cur++;
-
- break;
- }
- }
- cur++;
- if ( cur >= limit )
- {
- FT_ERROR(( "Z1_Get_Private_Dict:" ));
- FT_ERROR(( " could not find `eexec' keyword\n" ));
- error = T1_Err_Invalid_File_Format;
- goto Exit;
- }
- }
-
- /* now determine where to write the _encrypted_ binary private */
- /* dictionary. We overwrite the base dictionary for disk-based */
- /* resources and allocate a new block otherwise */
-
- size = parser->base_len - ( cur - parser->base_dict);
-
- if ( parser->in_memory )
- {
- /* note that we allocate one more byte to put a terminating `0' */
- if ( ALLOC( parser->private_dict, size + 1 ) )
- goto Fail;
- parser->private_len = size;
- }
- else
- {
- parser->single_block = 1;
- parser->private_dict = parser->base_dict;
- parser->private_len = size;
- parser->base_dict = 0;
- parser->base_len = 0;
- }
-
- /* now determine whether the private dictionary is encoded in binary */
- /* or hexadecimal ASCII format -- decode it accordingly */
-
- /* we need to access the next 4 bytes (after the final \r following */
- /* the `eexec' keyword); if they all are hexadecimal digits, then */
- /* we have a case of ASCII storage */
-
- if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
- hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
-
- /* binary encoding -- `simply' copy the private dict */
- MEM_Copy( parser->private_dict, cur, size );
-
- else
- {
- /* ASCII hexadecimal encoding */
-
- FT_Byte* write;
- FT_Int count;
-
-
- write = parser->private_dict;
- count = 0;
-
- for ( ;cur < limit; cur++ )
- {
- int hex1;
-
-
- /* check for newline */
- if ( cur[0] == '\r' || cur[0] == '\n' )
- continue;
-
- /* exit if we have a non-hexadecimal digit that isn't a newline */
- hex1 = hexa_value( cur[0] );
- if ( hex1 < 0 || cur + 1 >= limit )
- break;
-
- /* otherwise, store byte */
- *write++ = ( hex1 << 4 ) | hexa_value( cur[1] );
- count++;
- cur++;
- }
-
- /* put a safeguard */
- parser->private_len = write - parser->private_dict;
- *write++ = 0;
- }
- }
-
- /* we now decrypt the encoded binary private dictionary */
- Z1_Decrypt( parser->private_dict, parser->private_len, 55665 );
- parser->root.base = parser->private_dict;
- parser->root.cursor = parser->private_dict;
- parser->root.limit = parser->root.cursor + parser->private_len;
-
- Fail:
- Exit:
- return error;
- }
-
-
-/* END */
--- a/src/type1/z1parse.h
+++ /dev/null
@@ -1,140 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1parse.h */
-/* */
-/* Experimental Type 1 parser (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 Z1PARSE_H
-#define Z1PARSE_H
-
-#include <freetype/internal/t1types.h>
-#include <freetype/internal/ftstream.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
- /*************************************************************************/
- /* */
- /* <Struct> */
- /* Z1_Parser */
- /* */
- /* <Description> */
- /* A Z1_Parser is an object used to parse a Type 1 fonts very */
- /* quickly. */
- /* */
- /* <Fields> */
- /* root :: The root parser. */
- /* */
- /* stream :: The current input stream. */
- /* */
- /* base_dict :: A pointer to the top-level dictionary. */
- /* */
- /* base_len :: The length in bytes of the top dictionary. */
- /* */
- /* private_dict :: A pointer to the private dictionary. */
- /* */
- /* private_len :: The length in bytes of the private dictionary. */
- /* */
- /* in_pfb :: A boolean. Indicates that we are handling a PFB */
- /* file. */
- /* */
- /* in_memory :: A boolean. Indicates a memory-based stream. */
- /* */
- /* single_block :: A boolean. Indicates that the private dictionary */
- /* is stored in lieu of the base dictionary. */
- /* */
- typedef struct Z1_Parser_
- {
- T1_Parser root;
- FT_Stream stream;
-
- FT_Byte* base_dict;
- FT_Int base_len;
-
- FT_Byte* private_dict;
- FT_Int private_len;
-
- FT_Byte in_pfb;
- FT_Byte in_memory;
- FT_Byte single_block;
-
- } Z1_Parser;
-
-
-#define Z1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
-#define Z1_Done_Table( p ) \
- do \
- { \
- if ( (p)->funcs.done ) \
- (p)->funcs.done( p ); \
- } while ( 0 )
-#define Z1_Release_Table( p ) \
- do \
- { \
- if ( (p)->funcs.release ) \
- (p)->funcs.release( p ); \
- } while ( 0 )
-
-
-#define Z1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
-#define Z1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root )
-
-#define Z1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root )
-#define Z1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t )
-
-#define Z1_ToCoordArray( p, m, c ) \
- (p)->root.funcs.to_coord_array( &(p)->root, m, c )
-#define Z1_ToFixedArray( p, m, f, t ) \
- (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
-#define Z1_ToToken( p, t ) \
- (p)->root.funcs.to_token( &(p)->root, t )
-#define Z1_ToTokenArray( p, t, m, c ) \
- (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
-
-#define Z1_Load_Field( p, f, o, m, pf ) \
- (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
-#define Z1_Load_Field_Table( p, f, o, m, pf ) \
- (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
-
-
- LOCAL_DEF
- FT_Error Z1_New_Parser( Z1_Parser* parser,
- FT_Stream stream,
- FT_Memory memory,
- PSAux_Interface* psaux );
-
- LOCAL_DEF
- FT_Error Z1_Get_Private_Dict( Z1_Parser* parser );
-
- LOCAL_DEF
- void Z1_Decrypt( FT_Byte* buffer,
- FT_Int length,
- FT_UShort seed );
-
- LOCAL_DEF
- void Z1_Done_Parser( Z1_Parser* parser );
-
-
-#ifdef __cplusplus
- }
-#endif
-
-
-#endif /* Z1PARSE_H */
-
-
-/* END */
--- a/src/type1/z1tokens.h
+++ /dev/null
@@ -1,73 +1,0 @@
-/***************************************************************************/
-/* */
-/* z1tokens.h */
-/* */
-/* Experimental Type 1 tokenizer (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. */
-/* */
-/***************************************************************************/
-
-
-#undef FT_STRUCTURE
-#define FT_STRUCTURE T1_FontInfo
-#undef T1CODE
-#define T1CODE t1_field_font_info
-
- T1_FIELD_STRING( "version", version )
- T1_FIELD_STRING( "Notice", notice )
- T1_FIELD_STRING( "FullName", full_name )
- T1_FIELD_STRING( "FamilyName", family_name )
- T1_FIELD_STRING( "Weight", weight )
-
- T1_FIELD_NUM ( "ItalicAngle", italic_angle )
- T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch )
- T1_FIELD_NUM ( "UnderlinePosition", underline_position )
- T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
-
-
-#undef FT_STRUCTURE
-#define FT_STRUCTURE T1_Private
-#undef T1CODE
-#define T1CODE t1_field_private
-
- T1_FIELD_NUM ( "UniqueID", unique_id )
- T1_FIELD_NUM ( "lenIV", lenIV )
- T1_FIELD_NUM ( "LanguageGroup", language_group )
- T1_FIELD_NUM ( "password", password )
-
- T1_FIELD_FIXED ( "BlueScale", blue_scale )
- T1_FIELD_NUM ( "BlueShift", blue_shift )
- T1_FIELD_NUM ( "BlueFuzz", blue_fuzz )
-
- T1_FIELD_NUM_TABLE ( "BlueValues", blue_values, 14 )
- T1_FIELD_NUM_TABLE ( "OtherBlues", other_blues, 10 )
- T1_FIELD_NUM_TABLE ( "FamilyBlues", family_blues, 14 )
- T1_FIELD_NUM_TABLE ( "FamilyOtherBlues", family_other_blues, 10 )
-
- T1_FIELD_NUM_TABLE2( "StdHW", standard_width, 1 )
- T1_FIELD_NUM_TABLE2( "StdVW", standard_height, 1 )
- T1_FIELD_NUM_TABLE2( "MinFeature", min_feature, 2 )
-
- T1_FIELD_NUM_TABLE ( "StemSnapH", snap_widths, 12 )
- T1_FIELD_NUM_TABLE ( "StemSnapV", snap_heights, 12 )
-
-
-#undef FT_STRUCTURE
-#define FT_STRUCTURE T1_Font
-#undef T1CODE
-#define T1CODE t1_field_font_dict
-
- T1_FIELD_NUM( "PaintType", paint_type )
- T1_FIELD_NUM( "FontType", font_type )
- T1_FIELD_NUM( "StrokeWidth", stroke_width )
-
-
-/* END */