📄 ttraster.c
字号:
/******************************************************************* * * ttraster.c 1.5 * * The FreeType glyph rasterizer (body). * * Copyright 1996-1999 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * This file is part of the FreeType project, and may only be used * modified and distributed under the terms of the FreeType project * license, LICENSE.TXT. By continuing to use, modify, or distribute * this file you indicate that you have read the license and * understand and accept it fully. * * 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.4: * * Performance tuning. * * Changes between 1.4 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -