summaryrefslogtreecommitdiff
path: root/Build/source/libs/freetype/freetype-1.5/lib/ttraster.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/freetype/freetype-1.5/lib/ttraster.c')
-rw-r--r--Build/source/libs/freetype/freetype-1.5/lib/ttraster.c2725
1 files changed, 0 insertions, 2725 deletions
diff --git a/Build/source/libs/freetype/freetype-1.5/lib/ttraster.c b/Build/source/libs/freetype/freetype-1.5/lib/ttraster.c
deleted file mode 100644
index e8024546423..00000000000
--- a/Build/source/libs/freetype/freetype-1.5/lib/ttraster.c
+++ /dev/null
@@ -1,2725 +0,0 @@
-/*******************************************************************
- *
- * ttraster.c 1.5
- *
- * 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.
- *
- * NOTES:
- *
- * This version supports the following:
- *
- * - direct grayscaling
- * - sub-banding
- * - drop-out modes 4 and 5
- * - second pass for complete drop-out control (bitmap only)
- * - variable precision
- *
- * Changes between 1.5 and 1.3:
- *
- * Mainly performance tunings:
- *
- * - Line_Down() and Bezier_Down() now use the functions Line_Up()
- * and Bezier_Up() to do their work.
- * - optimized Split_Bezier()
- * - optimized linked lists used during sweeps
- *
- ******************************************************************/
-
-#include "ttraster.h"
-#include "ttdebug.h"
-#include "tttypes.h"
-#include "ttengine.h"
-#include "ttcalc.h" /* for TT_MulDiv only */
-
-#include "ttmemory.h" /* only used to allocate memory on engine init */
-
-/* required by the tracing mode */
-#undef TT_COMPONENT
-#define TT_COMPONENT trace_raster
-
-
-/* The default render pool size */
-#define RASTER_RENDER_POOL 64000
-
-/* The size of the two-lines intermediate bitmap used */
-/* for anti-aliasing */
-#define RASTER_GRAY_LINES 2048
-
-
-#define Raster_Err_None TT_Err_Ok
-#define Raster_Err_Not_Ini TT_Err_Raster_Not_Initialized
-#define Raster_Err_Overflow TT_Err_Raster_Pool_Overflow
-#define Raster_Err_Neg_Height TT_Err_Raster_Negative_Height
-#define Raster_Err_Invalid TT_Err_Raster_Invalid_Value
-#define Raster_Err_Gray_Unsupported TT_Err_Raster_Gray_Unsupported
-
-
-/* FMulDiv means "Fast MulDiv", it is uses in case where 'b' is typically */
-/* a small value and the result of (a*b) is known to fit in 32 bits. */
-#define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
-
-/* On the other hand, SMulDiv is for "Slow MulDiv", and is used typically */
-/* for clipping computations. It simply uses the TT_MulDiv() function */
-/* defined in "ttcalc.h" */
-/* */
-/* So, the following definition fits the bill nicely, and we don't need */
-/* to use the one in 'ttcalc' anymore, even for 16-bit systems... */
-#define SMulDiv TT_MulDiv
-
-
-/* Define DEBUG_RASTER if you want to generate a debug version of the */
-/* rasterizer. This will progressively draw the glyphs while all the */
-/* computation are done directly on the graphics screen (the glyphs */
-/* will be inverted). */
-
-/* Note that DEBUG_RASTER should only be used for debugging with b/w */
-/* rendering, not with gray levels. */
-
-/* The definition of DEBUG_RASTER should appear in the file */
-/* "ttconfig.h". */
-
-#ifdef DEBUG_RASTER
- extern Char* Vio; /* A pointer to VRAM or display buffer */
-#endif
-
-
-/* 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
-
-#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 */
-
- /* States of each line, arc and profile */
- enum TStates_
- {
- Unknown,
- Ascending,
- Descending,
- Flat
- };
-
- typedef enum TStates_ TStates;
-
- struct TProfile_;
- typedef struct TProfile_ TProfile;
- typedef TProfile* PProfile;
-
- struct TProfile_
- {
- TT_F26Dot6 X; /* current coordinate during sweep */
- PProfile link; /* link to next profile - various purpose */
- PStorage 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;
-
-
- /* I use the classic trick of two dummy records for the head and tail */
- /* of a linked list; this reduces tests in insertion/deletion/sorting. */
- /* NOTE: used during sweeps only. */
-
- /* Simple record used to implement a stack of bands, required */
- /* by the sub-banding mechanism */
-
- struct TBand_
- {
- Short y_min; /* band's minimum */
- Short y_max; /* band's maximum */
- };
-
- typedef struct TBand_ TBand;
-
-
-#define AlignProfileSize \
- (( sizeof(TProfile)+sizeof(long)-1 ) / sizeof(long))
-
-
- /* Left fill bitmask */
- static const Byte LMask[8] =
- { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
-
- /* Right fill bitmask */
- static const Byte RMask[8] =
- { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
-
- /* 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,
- TT_F26Dot6 x1,
- TT_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 )
-
-#ifdef DEBUG_RASTER
-#define DEBUG_PSET Pset()
-#else
-#define DEBUG_PSET
-#endif
-
- struct TPoint_
- {
- Long x, y;
- };
-
- typedef struct TPoint_ TPoint;
-
-
- /* 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 */
-
- PStorage buff; /* The profiles buffer */
- PStorage sizeBuff; /* Render pool size */
- PStorage maxBuff; /* Profiles buffer size */
- PStorage top; /* Current cursor in buffer */
-
- TT_Error error;
-
- PByte flags; /* current flags table */
- PUShort outs; /* current outlines table */
-
- UShort nPoints; /* number of points in current glyph */
- Short nContours; /* number of contours in current glyph */
- 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 */
-
- TT_Raster_Map target; /* description of target bit/pixmap */
-
- 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;
-
- TT_Vector* coords;
-
- Byte dropOutControl; /* current drop_out control method */
-
- Byte grays[5]; /* Palette of gray levels used for render */
-
- Byte* 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' */
-
- 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 */
- };
-
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
-
- static TRaster_Instance cur_ras;
-#define ras cur_ras
-
-#else
-
-#define ras (*raster)
-
-#endif /* TT_STATIC_RASTER */
-
-
-#ifdef DEBUG_RASTER
-
- /************************************************/
- /* */
- /* Pset: */
- /* */
- /* Used for debugging only. Plots a point */
- /* in VRAM during rendering (not afterwards). */
- /* */
- /* NOTE: This procedure relies on the value */
- /* of cProfile->start, which may not */
- /* be set when Pset is called sometimes. */
- /* This will usually result in a dot */
- /* plotted on the first screen scanline */
- /* (far away its original position). */
- /* */
- /* This "bug" reflects nothing wrong */
- /* in the current implementation, and */
- /* the bitmap is rendered correctly, */
- /* so don't panic if you see 'flying' */
- /* dots in debugging mode. */
- /* */
- /* - David */
- /* */
- /************************************************/
-
- static void Pset( RAS_ARG )
- {
- Long o;
- Long x;
-
-
- x = ras.top[-1];
-
- switch ( ras.cProfile->flow )
- {
- case TT_Flow_Up:
- o = Vio_ScanLineWidth *
- ( ras.top-ras.cProfile->offset + ras.cProfile->start ) +
- ( x / (ras.precision*8) );
- break;
-
- case TT_Flow_Down:
- o = Vio_ScanLineWidth *
- ( ras.cProfile->start-ras.top + ras.cProfile->offset ) +
- ( x / (ras.precision*8) );
- break;
- }
-
- if ( o > 0 )
- Vio[o] |= (unsigned)0x80 >> ( (x/ras.precision) & 7 );
- }
-
-
- static void Clear_Band( RAS_ARGS Int y1, Int y2 )
- {
- MEM_Set( Vio + y1*Vio_ScanLineWidth, (y2-y1+1)*Vio_ScanLineWidth, 0 );
- }
-
-#endif /* DEBUG_RASTER */
-
-
-/************************************************************************/
-/* */
-/* 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 Bool 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;
- }
-
- PTRACE7(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
-
- ras.precision = 1 << 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 state/orientation of the new Profile */
-/* */
-/* Returns: 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 = TT_Flow_Up;
- PTRACE7(( "New ascending profile = %lx\n", (long)ras.cProfile ));
- break;
-
- case Descending:
- ras.cProfile->flow = TT_Flow_Down;
- PTRACE7(( "New descending profile = %lx\n", (long)ras.cProfile ));
- break;
-
- default:
- PTRACE0(( "Invalid profile direction in Raster:New_Profile !!\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. */
-/* */
-/* Input: None */
-/* */
-/* Returns: 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 )
- {
- PTRACE0(( "Negative height encountered in End_Profile!\n" ));
- ras.error = Raster_Err_Neg_Height;
- return FAILURE;
- }
-
- if ( h > 0 )
- {
- PTRACE1(( "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 )
- {
- PTRACE1(( "overflow in End_Profile\n" ));
- ras.error = Raster_Err_Overflow;
- return FAILURE;
- }
-
- ras.joint = FALSE;
-
- return SUCCESS;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Insert_Y_Turn */
-/* */
-/* Description: Insert a salient into the sorted list placed on top */
-/* of the render pool */
-/* */
-/* Input: New y scanline position */
-/* */
-/****************************************************************************/
-
- static
- Bool Insert_Y_Turn( RAS_ARGS Int y )
- {
- PStorage 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. */
-/* */
-/* Input: None */
-/* */
-/* Returns: None. */
-/* */
-/****************************************************************************/
-
- static
- Bool Finalize_Profile_Table( RAS_ARG )
- {
- Long 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 TT_Flow_Down:
- bottom = p->start - p->height+1;
- top = p->start;
- p->start = bottom;
- p->offset += p->height-1;
- break;
-
- case TT_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_Bezier */
-/* */
-/* Description: Subdivides one Bezier arc into two joint */
-/* sub-arcs in the Bezier stack. */
-/* */
-/* Input: None (subdivided bezier is taken from the top of the */
-/* stack). */
-/* */
-/* Returns: None. */
-/* */
-/* */
-/* 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_Bezier( TPoint* base )
- {
- Long a, b;
-
-
- base[4].x = base[2].x;
- b = base[1].x;
- a = base[3].x = ( base[2].x + b ) / 2;
- b = base[1].x = ( base[0].x + b ) / 2;
- base[2].x = ( a + b ) / 2;
-
- base[4].y = base[2].y;
- b = base[1].y;
- a = base[3].y = ( base[2].y + b ) / 2;
- b = base[1].y = ( base[0].y + b ) / 2;
- base[2].y = ( a + b ) / 2;
-
- /* hand optimized. gcc doesn't seem too good at common expression */
- /* substitution and instruction scheduling ;-) */
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Push_Bezier */
-/* */
-/* Description: Clears the Bezier stack and pushes a new arc on top of it. */
-/* */
-/* Input: x1,y1 x2,y2 x3,y3 new Bezier arc */
-/* */
-/* Returns: None. */
-/* */
-/****************************************************************************/
-
- static void Push_Bezier( RAS_ARGS Long x1, Long y1,
- Long x2, Long y2,
- Long x3, Long y3 )
- {
- ras.arc = ras.arcs;
- ras.arc[2].x = x1; ras.arc[2].y = y1;
- ras.arc[1].x = x2; ras.arc[1].y = y2;
- ras.arc[0].x = x3; ras.arc[0].y = y3;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Line_Up */
-/* */
-/* Description: Computes the x-coordinates of an ascending line segment */
-/* and stores them in the render pool. */
-/* */
-/* Input: x1,y1,x2,y2 Segment start (x1,y1) and end (x2,y2) points */
-/* */
-/* Returns: 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;
-
- PStorage 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;
-
- DEBUG_PSET;
-
- x1 += Ix;
- Ax += Rx;
- if ( Ax >= 0 )
- {
- Ax -= Dy;
- x1 += Dx;
- }
- size--;
- }
-
- ras.top = top;
- return SUCCESS;
- }
-
-
- 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;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Bezier_Up */
-/* */
-/* Description: Computes thes x-coordinates of an ascending bezier arc */
-/* and stores them in the render pool. */
-/* */
-/* Input: None. The arc is taken from the top of the Bezier stack. */
-/* */
-/* Returns: SUCCESS on success. */
-/* FAILURE on Render Pool overflow. */
-/* */
-/****************************************************************************/
-
- static Bool Bezier_Up( RAS_ARGS Long miny, Long maxy )
- {
- Long y1, y2, e, e2, e0;
- Short f1;
-
- TPoint* arc;
- TPoint* start_arc;
-
- PStorage top;
-
-
- arc = ras.arc;
- y1 = arc[2].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[2].x;
-
- DEBUG_PSET;
-
- 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[2].y;
- if ( y2 - y1 >= ras.precision_step )
- {
- Split_Bezier( arc );
- arc += 2;
- }
- else
- {
- *top++ = arc[2].x + FMulDiv( arc[0].x - arc[2].x,
- e - y1,
- y2 - y1 );
- DEBUG_PSET;
-
- arc -= 2;
- e += ras.precision;
- }
- }
- else
- {
- if ( y2 == e )
- {
- ras.joint = TRUE;
- *top++ = arc[0].x;
-
- DEBUG_PSET;
-
- e += ras.precision;
- }
- arc -= 2;
- }
- }
-
- Fin:
- ras.top = top;
- ras.arc -= 2;
- return SUCCESS;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Bezier_Down */
-/* */
-/* Description: Computes the x-coordinates of a descending bezier arc */
-/* and stores them in the render pool. */
-/* */
-/* Input: None. Arc is taken from the top of the Bezier stack. */
-/* */
-/* Returns: SUCCESS on success. */
-/* FAILURE on Render Pool overflow. */
-/* */
-/****************************************************************************/
-
- static Bool Bezier_Down( RAS_ARGS 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;
-
- fresh = ras.fresh;
-
- result = Bezier_Up( RAS_VARS -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, y : segment endpoint (start point in LastX,LastY) */
-/* */
-/* Returns: 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: Bezier_To */
-/* */
-/* Description: Injects a new bezier arc and adjusts the profile list. */
-/* */
-/* Input: x, y : arc endpoint (start point in LastX, LastY) */
-/* Cx, Cy : control point */
-/* */
-/* Returns: SUCCESS on success. */
-/* FAILURE on Render Pool overflow or Incorrect Profile. */
-/* */
-/****************************************************************************/
-
- static Bool Bezier_To( RAS_ARGS Long x,
- Long y,
- Long cx,
- Long cy )
- {
- Long y1, y2, y3, x3;
- TStates state_bez;
-
-
- Push_Bezier( RAS_VARS ras.lastX, ras.lastY, cx, cy, x, 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 == y2 )
- {
- if ( y2 == y3 )
- state_bez = Flat;
- else if ( y2 > y3 )
- state_bez = Descending;
- else
- state_bez = Ascending;
- }
- else if ( y1 > y2 )
- {
- if ( y2 >= y3 )
- state_bez = Descending;
- else
- state_bez = Unknown;
- }
- else if ( y2 <= y3 )
- state_bez = Ascending;
- else
- state_bez = Unknown;
-
- /* split non-monotonic arcs, ignore flat ones, or */
- /* computes the up and down ones */
-
- switch ( state_bez )
- {
- case Flat:
- ras.arc -= 2;
- break;
-
- case Unknown:
- Split_Bezier( ras.arc );
- ras.arc += 2;
- break;
-
- default:
- /* detect a change of direction */
-
- if ( ras.state != state_bez )
- {
- if ( ras.state != Unknown )
- if ( End_Profile( RAS_VAR ) ) return FAILURE;
-
- if ( New_Profile( RAS_VARS state_bez ) ) return FAILURE;
- }
-
- /* compute */
-
- switch ( ras.state )
- {
- case Ascending:
- if ( Bezier_Up ( RAS_VARS ras.minY, ras.maxY ) )
- return FAILURE;
- break;
-
- case Descending:
- if ( Bezier_Down( RAS_VARS ras.minY, ras.maxY ) )
- return FAILURE;
- break;
-
- default:
- ;
- }
- }
- } while ( ras.arc >= ras.arcs );
-
- ras.lastX = x3;
- ras.lastY = y3;
-
- return SUCCESS;
- }
-
-
-/****************************************************************************/
-/* */
-/* 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, last : indexes of first and last point in */
-/* contour. */
-/* */
-/* Returns: SUCCESS on success. */
-/* FAILURE on error. */
-/* */
-/****************************************************************************/
-
-#undef SWAP_
-#define SWAP_(x,y) { Long swap = x; x = y; y = swap; }
-
- static Bool Decompose_Curve( RAS_ARGS UShort first,
- UShort last,
- Bool flipped )
- {
- Long x, y; /* current point */
- Long cx, cy; /* current Bezier control point */
- Long mx, my; /* current middle point */
-
- Long x_first, y_first; /* first point's coordinates */
- Long x_last, y_last; /* last point's coordinates */
-
- UShort index; /* current point's index */
- Bool on_curve; /* current point's state */
-
- x_first = SCALED( ras.coords[first].x );
- y_first = SCALED( ras.coords[first].y );
-
- if ( flipped ) SWAP_( x_first,y_first );
-
- x_last = SCALED( ras.coords[last].x );
- y_last = SCALED( ras.coords[last].y );
-
- if ( flipped ) SWAP_( x_last,y_last );
-
- ras.lastX = cx = x_first;
- ras.lastY = cy = y_first;
-
- on_curve = (ras.flags[first] & 1);
- index = first;
-
- /* check first point to determine origin */
- if ( !on_curve )
- {
- /* first point is off the curve. Yes, this happens... */
- if ( ras.flags[last] & 1 )
- {
- ras.lastX = x_last; /* start at last point if it */
- ras.lastY = y_last; /* is on the curve */
- }
- else
- {
- /* if both first and last points are off the curve, */
- /* start at their middle and record its position */
- /* for closure */
- ras.lastX = (ras.lastX + x_last)/2;
- ras.lastY = (ras.lastY + y_last)/2;
-
- x_last = ras.lastX;
- y_last = ras.lastY;
- }
- }
-
- /* now process each contour point individually */
- while ( index < last )
- {
- index++;
- x = SCALED( ras.coords[index].x );
- y = SCALED( ras.coords[index].y );
-
- if ( flipped ) SWAP_( x, y );
-
- if ( on_curve )
- {
- /* the previous point was on the curve */
- on_curve = ( ras.flags[index] & 1 );
- if ( on_curve )
- {
- /* two successive on points => emit segment */
- if ( Line_To( RAS_VARS x, y ) ) return FAILURE;
- }
- else
- {
- /* else, keep current control point for next bezier */
- cx = x;
- cy = y;
- }
- }
- else
- {
- /* the previous point was off the curve */
- on_curve = ( ras.flags[index] & 1 );
- if ( on_curve )
- {
- /* reaching an `on' point */
- if ( Bezier_To( RAS_VARS x, y, cx, cy ) ) return FAILURE;
- }
- else
- {
- /* two successive `off' points => create middle point */
- mx = ( cx + x ) / 2;
- my = ( cy + y ) / 2;
-
- if ( Bezier_To( RAS_VARS mx, my, cx, cy ) ) return FAILURE;
-
- cx = x;
- cy = y;
- }
- }
- }
-
- /* end of contour, close curve cleanly */
- if ( ras.flags[first] & 1 )
- {
- if ( on_curve )
- return Line_To( RAS_VARS x_first, y_first );
- else
- return Bezier_To( RAS_VARS x_first, y_first, cx, cy );
- }
- else
- if ( !on_curve )
- return Bezier_To( RAS_VARS x_last, y_last, cx, cy );
-
- return SUCCESS;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Convert_Glyph */
-/* */
-/* Description: Converts a glyph into a series of segments and arcs */
-/* and makes a Profiles list with them. */
-/* */
-/* Input: _xCoord, _yCoord : coordinates tables. */
-/* */
-/* Uses the 'Flag' table too. */
-/* */
-/* Returns: 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.nContours; i++ )
- {
- ras.state = Unknown;
- ras.gProfile = NULL;
-
- if ( Decompose_Curve( RAS_VARS start, ras.outs[i], flipped ) )
- return FAILURE;
-
- start = ras.outs[i] + 1;
-
- /* We must now see if 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 );
- }
-
-
-/************************************************/
-/* */
-/* Init_Linked */
-/* */
-/* Inits 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 = &current->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 = &current->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 = &current->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 three 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 )
- {
- switch ( ras.target.flow )
- {
- case TT_Flow_Up:
- ras.traceOfs = *min * ras.target.cols;
- ras.traceIncr = ras.target.cols;
- break;
-
- default:
- ras.traceOfs = ( ras.target.rows - 1 - *min ) * ras.target.cols;
- ras.traceIncr = -ras.target.cols;
- }
-
- ras.gray_min_x = 0;
- ras.gray_max_x = 0;
- }
-
-
- static void Vertical_Sweep_Span( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- Short c1, c2;
- Short f1, f2;
- Byte* target;
-
-
- /* 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 = e1 & 7;
- f2 = 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;
-
- if ( c1 != c2 )
- {
- *target |= LMask[f1];
-
- if ( c2 > c1 + 1 )
- MEM_Set( target + 1, 0xFF, c2 - c1 - 1 );
-
- target[c2 - c1] |= RMask[f2];
- }
- else
- *target |= ( LMask[f1] & RMask[f2] );
- }
- }
-
-
- static void Vertical_Sweep_Drop( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_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 when: */
- /* */
- /* 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 ( x2-x1 < ras.precision_half ) */
- {
- /* 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 three 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 */
- }
-
-
- static void Horizontal_Sweep_Span( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- Long e1, e2;
- PByte bits;
- Byte f1;
-
-
- 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 )
- {
- if ( ras.target.flow == TT_Flow_Down )
- bits[(ras.target.rows-1 - e1) * ras.target.cols] |= f1;
- else
- bits[e1 * ras.target.cols] |= f1;
- }
- }
- }
-#if 0
- e2 = TRUNC( e2 );
-
- if ( e2 >= 0 && e2 < ras.target.rows )
- if ( ras.target.flow == TT_Flow_Down )
- bits[(ras.target.rows-1-e2) * ras.target.cols] |= f1;
- else
- bits[e2 * ras.target.cols] |= f1;
-#endif
- }
-
-
- static void Horizontal_Sweep_Drop( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_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));
-
- if ( ras.target.flow == TT_Flow_Down )
- bits += (ras.target.rows-1-e1) * ras.target.cols;
- else
- bits += e1 * ras.target.cols;
-
- 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 )
- {
- if (ras.target.flow==TT_Flow_Down)
- bits[(ras.target.rows-1-e1) * ras.target.cols] |= f1;
- else
- bits[e1 * ras.target.cols] |= f1;
- }
- }
-
-
- static void Horizontal_Sweep_Step( RAS_ARG )
- {
- /* Nothing, really */
- }
-
-
-#ifdef TT_CONFIG_OPTION_GRAY_SCALING
-
-/***********************************************************************/
-/* */
-/* 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 )
- {
- *min = *min & -2;
- *max = ( *max + 3 ) & -2;
-
- ras.traceOfs = 0;
-
- switch ( ras.target.flow )
- {
- case TT_Flow_Up:
- ras.traceG = (*min / 2) * ras.target.cols;
- ras.traceIncr = ras.target.cols;
- break;
-
- default:
- ras.traceG = (ras.target.rows-1 - *min/2) * ras.target.cols;
- ras.traceIncr = -ras.target.cols;
- }
-
- ras.gray_min_x = ras.target.cols;
- ras.gray_max_x = -ras.target.cols;
- }
-
-
- 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 )
- {
- if ( ras.gray_max_x >= ras.target.width )
- ras.gray_max_x = ras.target.width-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 & 0xF000) >> 12];
- pix[1] = grays[(c2 & 0x0F00) >> 8];
- pix[2] = grays[(c2 & 0x00F0) >> 4];
- pix[3] = grays[(c2 & 0x000F) ];
-
- *bit = 0;
- *bit2 = 0;
- }
-
- bit ++;
- bit2++;
- pix += 4;
- c1 --;
- }
- }
-
- ras.traceOfs = 0;
- ras.traceG += ras.traceIncr;
-
- ras.gray_min_x = ras.target.cols;
- ras.gray_max_x = -ras.target.cols;
- }
- }
-
-
- static void Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_F26Dot6 x2,
- PProfile left,
- PProfile right )
- {
- /* nothing, really */
- }
-
- static void Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
- TT_F26Dot6 x1,
- TT_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 )
- {
- if ( ras.target.flow == TT_Flow_Down )
- pixel = ras.gTarget +
- (ras.target.rows - 1 - e1) * ras.target.cols + y / 2;
- else
- pixel = ras.gTarget +
- e1 * ras.target.cols + y / 2;
-
- if (pixel[0] == ras.grays[0])
- pixel[0] = color;
- }
- }
- }
-
-#endif /* TT_CONFIG_OPTION_GRAY_SCALING */
-
-
-/********************************************************************/
-/* */
-/* 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 = P->start;
- top = 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 TT_Flow_Up: InsNew( &draw_left, P ); break;
- case TT_Flow_Down: InsNew( &draw_right, P ); break;
- }
- }
-
- P = Q;
- }
-
- /* Sort the drawing lists */
-
- Sort( &draw_left );
- Sort( &draw_right );
-
- y_change = (Short)ras.sizeBuff[-ras.numTurns--];
- y_height = y_change - y;
-
- while ( y < y_change )
- {
-
- /* Let's trace */
-
- dropouts = 0;
-
- P_Left = draw_left;
- P_Right = draw_right;
-
- while ( P_Left )
- {
- x1 = P_Left ->X;
- x2 = P_Right->X;
-
- if ( x1 > x2 )
- {
- xs = x1;
- x1 = x2;
- x2 = xs;
- }
-
- if ( x2-x1 <= ras.precision )
- {
- e1 = FLOOR( x1 );
- e2 = CEILING( x2 );
-
- if ( ras.dropOutControl != 0 &&
- (e1 > e2 || e2 == e1 + ras.precision) )
- {
- /* a drop out was detected */
-
- P_Left ->X = x1;
- P_Right->X = x2;
-
- /* mark profile for drop-out processing */
- P_Left->countL = 1;
- dropouts++;
-
- goto Skip_To_Next;
- }
- }
-
- ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
-
- Skip_To_Next:
-
- P_Left = P_Left->link;
- P_Right = P_Right->link;
- }
-
- /* now perform the dropouts _after_ the span drawing */
- /* drop-outs processing has been moved out of the loop */
- /* for performance tuning */
- if (dropouts > 0)
- goto Scan_DropOuts;
-
- Next_Line:
-
- ras.Proc_Sweep_Step( RAS_VAR );
-
- y++;
-
- if ( y < y_change )
- {
- Sort( &draw_left );
- Sort( &draw_right );
- }
-
- }
-
- /* Now finalize the profiles that needs it */
-
- {
- PProfile Q, P;
- P = draw_left;
- while ( P )
- {
- Q = P->link;
- if ( P->height == 0 )
- DelOld( &draw_left, P );
- P = Q;
- }
- }
-
- {
- PProfile Q, P = draw_right;
- while ( P )
- {
- Q = P->link;
- if ( P->height == 0 )
- DelOld( &draw_right, P );
- P = Q;
- }
- }
- }
-
- /* for gray-scaling, flushes the bitmap scanline cache */
- while ( y <= max_Y )
- {
- ras.Proc_Sweep_Step( RAS_VAR );
- y++;
- }
-
- return SUCCESS;
-
-Scan_DropOuts :
-
- P_Left = draw_left;
- P_Right = draw_right;
-
- while ( P_Left )
- {
- if ( P_Left->countL )
- {
- P_Left->countL = 0;
- /* dropouts--; -- this is useful when debugging only */
- 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: _XCoord, _YCoord : x and y coordinates arrays */
-/* */
-/* Returns: SUCCESS on success */
-/* FAILURE if any error was encountered during render. */
-/* */
-/****************************************************************************/
-
- static TT_Error 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 TT_Err_Ok;
- }
-
-
-/****************************************************************************/
-/* */
-/* Function: Render_Glyph */
-/* */
-/* Description: Renders a glyph in a bitmap. Sub-banding if needed. */
-/* */
-/* Input: AGlyph Glyph record */
-/* */
-/* Returns: SUCCESS on success. */
-/* FAILURE if any error was encountered during rendering. */
-/* */
-/****************************************************************************/
-
- FT_INTERNAL_FUNC( TT_Error )
- Render_Glyph( RAS_ARGS TT_Outline* glyph,
- TT_Raster_Map* target_map )
- {
- TT_Error error;
-
-
- if ( glyph->n_points == 0 || glyph->n_contours <= 0 )
- return TT_Err_Ok;
-
- if ( !ras.buff )
- {
- ras.error = Raster_Err_Not_Ini;
- return ras.error;
- }
-
- if ( glyph->n_points < glyph->contours[glyph->n_contours - 1] )
- {
- ras.error = TT_Err_Too_Many_Points;
- return ras.error;
- }
-
- if ( target_map )
- ras.target = *target_map;
-
- ras.outs = glyph->contours;
- ras.flags = glyph->flags;
- ras.nPoints = glyph->n_points;
- ras.nContours = glyph->n_contours;
- ras.coords = glyph->points;
-
- Set_High_Precision( RAS_VARS glyph->high_precision );
- ras.scale_shift = ras.precision_shift;
- ras.dropOutControl = glyph->dropout_mode;
- ras.second_pass = glyph->second_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.bitmap;
-
- 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 TT_Err_Ok;
- }
-
-
-#ifdef TT_CONFIG_OPTION_GRAY_SCALING
-
-/****************************************************************************/
-/* */
-/* Function: Render_Gray_Glyph */
-/* */
-/* Description: Renders a glyph with grayscaling. Sub-banding if needed. */
-/* */
-/* Input: AGlyph Glyph record */
-/* */
-/* Returns: SUCCESS on success */
-/* FAILURE if any error was encountered during rendering. */
-/* */
-/****************************************************************************/
-
- FT_INTERNAL_FUNC( TT_Error )
- Render_Gray_Glyph( RAS_ARGS TT_Outline* glyph,
- TT_Raster_Map* target_map,
- Byte* palette )
- {
- Int i;
- TT_Error error;
-
- if ( !ras.buff )
- {
- ras.error = Raster_Err_Not_Ini;
- return ras.error;
- }
-
- if ( glyph->n_points == 0 || glyph->n_contours <= 0 )
- return TT_Err_Ok;
-
- if ( glyph->n_points < glyph->contours[glyph->n_contours - 1] )
- {
- ras.error = TT_Err_Too_Many_Points;
- return ras.error;
- }
-
- if ( palette )
- {
- for ( i = 0; i < 5; i++ )
- ras.grays[i] = palette[i];
- }
-
- if ( target_map )
- ras.target = *target_map;
-
- ras.outs = glyph->contours;
- ras.flags = glyph->flags;
- ras.nPoints = glyph->n_points;
- ras.nContours = glyph->n_contours;
- ras.coords = glyph->points;
-
- Set_High_Precision( RAS_VARS glyph->high_precision );
- ras.scale_shift = ras.precision_shift+1;
- ras.dropOutControl = glyph->dropout_mode;
- ras.second_pass = glyph->second_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;
- if ( ras.bWidth > ras.target.cols/4 )
- ras.bWidth = ras.target.cols/4;
-
- ras.bWidth = ras.bWidth * 8;
- ras.bTarget = (Byte*)ras.gray_lines;
- ras.gTarget = (Byte*)ras.target.bitmap;
-
- 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 TT_Err_Ok;
- }
-
-#endif /* TT_CONFIG_OPTION_GRAY_SCALING */
-
-
-/************************************************/
-/* */
-/* InitRasterizer */
-/* */
-/* Raster Initialization. */
-/* Gets the bitmap description and render pool */
-/* addresses. */
-/* */
-/************************************************/
-
-#undef ras
-
- FT_INTERNAL_FUNC( TT_Error )
- TTRaster_Done( PEngine_Instance engine )
- {
- TRaster_Instance* ras = (TRaster_Instance*)engine->raster_component;
-
-
- if ( !ras )
- return TT_Err_Ok;
-
- FREE( ras->buff );
- FREE( ras->gray_lines );
-
-#ifndef TT_CONFIG_OPTION_STATIC_RASTER
- FREE( engine->raster_component );
-#endif
-
- return TT_Err_Ok;
- }
-
-
- FT_INTERNAL_FUNC( TT_Error )
- TTRaster_Init( PEngine_Instance engine )
- {
- TT_Error error;
-
- Int i, l, j, c;
-
- TRaster_Instance* ras;
-
-
-#ifdef TT_CONFIG_OPTION_STATIC_RASTER
- ras = engine->raster_component = &cur_ras;
-#else
- if ( ALLOC( engine->raster_component, sizeof ( TRaster_Instance ) ) )
- return error;
-
- ras = (TRaster_Instance*)engine->raster_component;
-#endif
-
- if ( ALLOC( ras->buff, RASTER_RENDER_POOL ) ||
- ALLOC( ras->gray_lines, RASTER_GRAY_LINES ) )
- return error;
-
- ras->sizeBuff = ras->buff + ( RASTER_RENDER_POOL/sizeof(long) );
- ras->gray_width = RASTER_GRAY_LINES/2;
-
- MUTEX_Create( engine->raster_lock );
-
- /* Initialization of Count_Table */
-
- for ( i = 0; i < 256; i++ )
- {
- l = 0;
- j = i;
-
- for ( c = 0; c < 4; c++ )
- {
- l <<= 4;
-
- if ( j & 0x80 ) l++;
- if ( j & 0x40 ) l++;
-
- j = ( j << 2 ) & 0xFF;
- }
-
- ras->count_table[i] = l;
- }
-
- ras->dropOutControl = 2;
- ras->error = Raster_Err_None;
-
- return TT_Err_Ok;
- }
-
-
-/* END */