xref: /inferno-os/libfreetype/ftraster.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftraster.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    The FreeType glyph rasterizer (body).                                */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth   /*************************************************************************/
19*37da2899SCharles.Forsyth   /*                                                                       */
20*37da2899SCharles.Forsyth   /* This is a rewrite of the FreeType 1.x scan-line converter             */
21*37da2899SCharles.Forsyth   /*                                                                       */
22*37da2899SCharles.Forsyth   /*************************************************************************/
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth #include <ft2build.h>
26*37da2899SCharles.Forsyth #include "ftraster.h"
27*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth   /*                                                                       */
32*37da2899SCharles.Forsyth   /* A simple technical note on how the raster works                       */
33*37da2899SCharles.Forsyth   /* -----------------------------------------------                       */
34*37da2899SCharles.Forsyth   /*                                                                       */
35*37da2899SCharles.Forsyth   /*   Converting an outline into a bitmap is achieved in several steps:   */
36*37da2899SCharles.Forsyth   /*                                                                       */
37*37da2899SCharles.Forsyth   /*   1 - Decomposing the outline into successive `profiles'.  Each       */
38*37da2899SCharles.Forsyth   /*       profile is simply an array of scanline intersections on a given */
39*37da2899SCharles.Forsyth   /*       dimension.  A profile's main attributes are                     */
40*37da2899SCharles.Forsyth   /*                                                                       */
41*37da2899SCharles.Forsyth   /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
42*37da2899SCharles.Forsyth   /*                                                                       */
43*37da2899SCharles.Forsyth   /*       o an array of intersection coordinates for each scanline        */
44*37da2899SCharles.Forsyth   /*         between `Ymin' and `Ymax'.                                    */
45*37da2899SCharles.Forsyth   /*                                                                       */
46*37da2899SCharles.Forsyth   /*       o a direction, indicating whether it was built going `up' or    */
47*37da2899SCharles.Forsyth   /*         `down', as this is very important for filling rules.          */
48*37da2899SCharles.Forsyth   /*                                                                       */
49*37da2899SCharles.Forsyth   /*   2 - Sweeping the target map's scanlines in order to compute segment */
50*37da2899SCharles.Forsyth   /*       `spans' which are then filled.  Additionally, this pass         */
51*37da2899SCharles.Forsyth   /*       performs drop-out control.                                      */
52*37da2899SCharles.Forsyth   /*                                                                       */
53*37da2899SCharles.Forsyth   /*   The outline data is parsed during step 1 only.  The profiles are    */
54*37da2899SCharles.Forsyth   /*   built from the bottom of the render pool, used as a stack.  The     */
55*37da2899SCharles.Forsyth   /*   following graphics shows the profile list under construction:       */
56*37da2899SCharles.Forsyth   /*                                                                       */
57*37da2899SCharles.Forsyth   /*     ____________________________________________________________ _ _  */
58*37da2899SCharles.Forsyth   /*    |         |                   |         |                 |        */
59*37da2899SCharles.Forsyth   /*    | profile | coordinates for   | profile | coordinates for |-->     */
60*37da2899SCharles.Forsyth   /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
61*37da2899SCharles.Forsyth   /*    |_________|___________________|_________|_________________|__ _ _  */
62*37da2899SCharles.Forsyth   /*                                                                       */
63*37da2899SCharles.Forsyth   /*    ^                                                         ^        */
64*37da2899SCharles.Forsyth   /*    |                                                         |        */
65*37da2899SCharles.Forsyth   /*  start of render pool                                       top       */
66*37da2899SCharles.Forsyth   /*                                                                       */
67*37da2899SCharles.Forsyth   /*   The top of the profile stack is kept in the `top' variable.         */
68*37da2899SCharles.Forsyth   /*                                                                       */
69*37da2899SCharles.Forsyth   /*   As you can see, a profile record is pushed on top of the render     */
70*37da2899SCharles.Forsyth   /*   pool, which is then followed by its coordinates/intersections.  If  */
71*37da2899SCharles.Forsyth   /*   a change of direction is detected in the outline, a new profile is  */
72*37da2899SCharles.Forsyth   /*   generated until the end of the outline.                             */
73*37da2899SCharles.Forsyth   /*                                                                       */
74*37da2899SCharles.Forsyth   /*   Note that when all profiles have been generated, the function       */
75*37da2899SCharles.Forsyth   /*   Finalize_Profile_Table() is used to record, for each profile, its   */
76*37da2899SCharles.Forsyth   /*   bottom-most scanline as well as the scanline above its upmost       */
77*37da2899SCharles.Forsyth   /*   boundary.  These positions are called `y-turns' because they (sort  */
78*37da2899SCharles.Forsyth   /*   of) correspond to local extrema.  They are stored in a sorted list  */
79*37da2899SCharles.Forsyth   /*   built from the top of the render pool as a downwards stack:         */
80*37da2899SCharles.Forsyth   /*                                                                       */
81*37da2899SCharles.Forsyth   /*      _ _ _______________________________________                      */
82*37da2899SCharles.Forsyth   /*                            |                    |                     */
83*37da2899SCharles.Forsyth   /*                         <--| sorted list of     |                     */
84*37da2899SCharles.Forsyth   /*                         <--|  extrema scanlines |                     */
85*37da2899SCharles.Forsyth   /*      _ _ __________________|____________________|                     */
86*37da2899SCharles.Forsyth   /*                                                                       */
87*37da2899SCharles.Forsyth   /*                            ^                    ^                     */
88*37da2899SCharles.Forsyth   /*                            |                    |                     */
89*37da2899SCharles.Forsyth   /*                         maxBuff           sizeBuff = end of pool      */
90*37da2899SCharles.Forsyth   /*                                                                       */
91*37da2899SCharles.Forsyth   /*   This list is later used during the sweep phase in order to          */
92*37da2899SCharles.Forsyth   /*   optimize performance (see technical note on the sweep below).       */
93*37da2899SCharles.Forsyth   /*                                                                       */
94*37da2899SCharles.Forsyth   /*   Of course, the raster detects whether the two stacks collide and    */
95*37da2899SCharles.Forsyth   /*   handles the situation propertly.                                    */
96*37da2899SCharles.Forsyth   /*                                                                       */
97*37da2899SCharles.Forsyth   /*************************************************************************/
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth   /*************************************************************************/
101*37da2899SCharles.Forsyth   /*************************************************************************/
102*37da2899SCharles.Forsyth   /**                                                                     **/
103*37da2899SCharles.Forsyth   /**  CONFIGURATION MACROS                                               **/
104*37da2899SCharles.Forsyth   /**                                                                     **/
105*37da2899SCharles.Forsyth   /*************************************************************************/
106*37da2899SCharles.Forsyth   /*************************************************************************/
107*37da2899SCharles.Forsyth 
108*37da2899SCharles.Forsyth   /* define DEBUG_RASTER if you want to compile a debugging version */
109*37da2899SCharles.Forsyth #define xxxDEBUG_RASTER
110*37da2899SCharles.Forsyth 
111*37da2899SCharles.Forsyth   /* The default render pool size in bytes */
112*37da2899SCharles.Forsyth #define RASTER_RENDER_POOL  8192
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth   /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
115*37da2899SCharles.Forsyth   /* 5-levels anti-aliasing                                                */
116*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
117*37da2899SCharles.Forsyth #define FT_RASTER_OPTION_ANTI_ALIASING
118*37da2899SCharles.Forsyth #endif
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth   /* The size of the two-lines intermediate bitmap used */
121*37da2899SCharles.Forsyth   /* for anti-aliasing, in bytes.                       */
122*37da2899SCharles.Forsyth #define RASTER_GRAY_LINES  2048
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth   /*************************************************************************/
126*37da2899SCharles.Forsyth   /*************************************************************************/
127*37da2899SCharles.Forsyth   /**                                                                     **/
128*37da2899SCharles.Forsyth   /**  OTHER MACROS (do not change)                                       **/
129*37da2899SCharles.Forsyth   /**                                                                     **/
130*37da2899SCharles.Forsyth   /*************************************************************************/
131*37da2899SCharles.Forsyth   /*************************************************************************/
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth   /*************************************************************************/
134*37da2899SCharles.Forsyth   /*                                                                       */
135*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
136*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
137*37da2899SCharles.Forsyth   /* messages during execution.                                            */
138*37da2899SCharles.Forsyth   /*                                                                       */
139*37da2899SCharles.Forsyth #undef  FT_COMPONENT
140*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_raster
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth #ifdef _STANDALONE_
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth   /* This macro is used to indicate that a function parameter is unused. */
147*37da2899SCharles.Forsyth   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
148*37da2899SCharles.Forsyth   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
149*37da2899SCharles.Forsyth   /* ANSI compilers (e.g. LCC).                                          */
150*37da2899SCharles.Forsyth #define FT_UNUSED( x )  (x) = (x)
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth   /* Disable the tracing mechanism for simplicity -- developers can      */
153*37da2899SCharles.Forsyth   /* activate it easily by redefining these two macros.                  */
154*37da2899SCharles.Forsyth #ifndef FT_ERROR
155*37da2899SCharles.Forsyth #define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
156*37da2899SCharles.Forsyth #endif
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth #ifndef FT_TRACE
159*37da2899SCharles.Forsyth #define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
160*37da2899SCharles.Forsyth #endif
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth #define Raster_Err_None          0
163*37da2899SCharles.Forsyth #define Raster_Err_Not_Ini      -1
164*37da2899SCharles.Forsyth #define Raster_Err_Overflow     -2
165*37da2899SCharles.Forsyth #define Raster_Err_Neg_Height   -3
166*37da2899SCharles.Forsyth #define Raster_Err_Invalid      -4
167*37da2899SCharles.Forsyth #define Raster_Err_Unsupported  -5
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth 
170*37da2899SCharles.Forsyth #else /* _STANDALONE_ */
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
174*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth #include "rasterrs.h"
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth #define Raster_Err_None         Raster_Err_Ok
179*37da2899SCharles.Forsyth #define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
180*37da2899SCharles.Forsyth #define Raster_Err_Overflow     Raster_Err_Raster_Overflow
181*37da2899SCharles.Forsyth #define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
182*37da2899SCharles.Forsyth #define Raster_Err_Invalid      Raster_Err_Invalid_Outline
183*37da2899SCharles.Forsyth #define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
184*37da2899SCharles.Forsyth 
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth #endif /* _STANDALONE_ */
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth #ifndef FT_MEM_SET
190*37da2899SCharles.Forsyth #define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
191*37da2899SCharles.Forsyth #endif
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth   /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
195*37da2899SCharles.Forsyth   /* typically a small value and the result of a*b is known to fit into */
196*37da2899SCharles.Forsyth   /* 32 bits.                                                           */
197*37da2899SCharles.Forsyth #define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
200*37da2899SCharles.Forsyth   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
201*37da2899SCharles.Forsyth   /* defined in `ftcalc.h'.                                                */
202*37da2899SCharles.Forsyth #define SMulDiv  FT_MulDiv
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth   /* The rasterizer is a very general purpose component; please leave */
205*37da2899SCharles.Forsyth   /* the following redefinitions there (you never know your target    */
206*37da2899SCharles.Forsyth   /* environment).                                                    */
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth #ifndef TRUE
209*37da2899SCharles.Forsyth #define TRUE   1
210*37da2899SCharles.Forsyth #endif
211*37da2899SCharles.Forsyth 
212*37da2899SCharles.Forsyth #ifndef FALSE
213*37da2899SCharles.Forsyth #define FALSE  0
214*37da2899SCharles.Forsyth #endif
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth #ifndef NULL
217*37da2899SCharles.Forsyth #define NULL  (void*)0
218*37da2899SCharles.Forsyth #endif
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth #ifndef SUCCESS
221*37da2899SCharles.Forsyth #define SUCCESS  0
222*37da2899SCharles.Forsyth #endif
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth #ifndef FAILURE
225*37da2899SCharles.Forsyth #define FAILURE  1
226*37da2899SCharles.Forsyth #endif
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth #define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
230*37da2899SCharles.Forsyth                         /* Setting this constant to more than 32 is a   */
231*37da2899SCharles.Forsyth                         /* pure waste of space.                         */
232*37da2899SCharles.Forsyth 
233*37da2899SCharles.Forsyth #define Pixel_Bits  6   /* fractional bits of *input* coordinates */
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth   /*************************************************************************/
237*37da2899SCharles.Forsyth   /*************************************************************************/
238*37da2899SCharles.Forsyth   /**                                                                     **/
239*37da2899SCharles.Forsyth   /**  SIMPLE TYPE DECLARATIONS                                           **/
240*37da2899SCharles.Forsyth   /**                                                                     **/
241*37da2899SCharles.Forsyth   /*************************************************************************/
242*37da2899SCharles.Forsyth   /*************************************************************************/
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth   typedef int             Int;
245*37da2899SCharles.Forsyth   typedef unsigned int    UInt;
246*37da2899SCharles.Forsyth   typedef short           Short;
247*37da2899SCharles.Forsyth   typedef unsigned short  UShort, *PUShort;
248*37da2899SCharles.Forsyth   typedef long            Long, *PLong;
249*37da2899SCharles.Forsyth   typedef unsigned long   ULong;
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth   typedef unsigned char   Byte, *PByte;
252*37da2899SCharles.Forsyth   typedef char            Bool;
253*37da2899SCharles.Forsyth 
254*37da2899SCharles.Forsyth   typedef struct  TPoint_
255*37da2899SCharles.Forsyth   {
256*37da2899SCharles.Forsyth     Long  x;
257*37da2899SCharles.Forsyth     Long  y;
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth   } TPoint;
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth   typedef enum  TFlow_
263*37da2899SCharles.Forsyth   {
264*37da2899SCharles.Forsyth     Flow_None = 0,
265*37da2899SCharles.Forsyth     Flow_Up   = 1,
266*37da2899SCharles.Forsyth     Flow_Down = -1
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth   } TFlow;
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth   /* States of each line, arc, and profile */
272*37da2899SCharles.Forsyth   typedef enum  TStates_
273*37da2899SCharles.Forsyth   {
274*37da2899SCharles.Forsyth     Unknown_State,
275*37da2899SCharles.Forsyth     Ascending_State,
276*37da2899SCharles.Forsyth     Descending_State,
277*37da2899SCharles.Forsyth     Flat_State
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth   } TStates;
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth   typedef struct TProfile_  TProfile;
283*37da2899SCharles.Forsyth   typedef TProfile*         PProfile;
284*37da2899SCharles.Forsyth 
285*37da2899SCharles.Forsyth   struct  TProfile_
286*37da2899SCharles.Forsyth   {
287*37da2899SCharles.Forsyth     FT_F26Dot6  X;           /* current coordinate during sweep        */
288*37da2899SCharles.Forsyth     PProfile    link;        /* link to next profile - various purpose */
289*37da2899SCharles.Forsyth     PLong       offset;      /* start of profile's data in render pool */
290*37da2899SCharles.Forsyth     int         flow;        /* Profile orientation: Asc/Descending    */
291*37da2899SCharles.Forsyth     long        height;      /* profile's height in scanlines          */
292*37da2899SCharles.Forsyth     long        start;       /* profile's starting scanline            */
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth     unsigned    countL;      /* number of lines to step before this    */
295*37da2899SCharles.Forsyth                              /* profile becomes drawable               */
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth     PProfile    next;        /* next profile in same contour, used     */
298*37da2899SCharles.Forsyth                              /* during drop-out control                */
299*37da2899SCharles.Forsyth   };
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth   typedef PProfile   TProfileList;
302*37da2899SCharles.Forsyth   typedef PProfile*  PProfileList;
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth   /* Simple record used to implement a stack of bands, required */
306*37da2899SCharles.Forsyth   /* by the sub-banding mechanism                               */
307*37da2899SCharles.Forsyth   typedef struct  TBand_
308*37da2899SCharles.Forsyth   {
309*37da2899SCharles.Forsyth     Short  y_min;   /* band's minimum */
310*37da2899SCharles.Forsyth     Short  y_max;   /* band's maximum */
311*37da2899SCharles.Forsyth 
312*37da2899SCharles.Forsyth   } TBand;
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth 
315*37da2899SCharles.Forsyth #define AlignProfileSize \
316*37da2899SCharles.Forsyth           ( ( sizeof ( TProfile ) + sizeof ( long ) - 1 ) / sizeof ( long ) )
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth #ifdef TT_STATIC_RASTER
320*37da2899SCharles.Forsyth 
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth #define RAS_ARGS       /* void */
323*37da2899SCharles.Forsyth #define RAS_ARG        /* void */
324*37da2899SCharles.Forsyth 
325*37da2899SCharles.Forsyth #define RAS_VARS       /* void */
326*37da2899SCharles.Forsyth #define RAS_VAR        /* void */
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth #define FT_UNUSED_RASTER  do ; while ( 0 )
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth #else /* TT_STATIC_RASTER */
332*37da2899SCharles.Forsyth 
333*37da2899SCharles.Forsyth 
334*37da2899SCharles.Forsyth #define RAS_ARGS       TRaster_Instance*  raster,
335*37da2899SCharles.Forsyth #define RAS_ARG        TRaster_Instance*  raster
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth #define RAS_VARS       raster,
338*37da2899SCharles.Forsyth #define RAS_VAR        raster
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth #define FT_UNUSED_RASTER  FT_UNUSED( raster )
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth 
343*37da2899SCharles.Forsyth #endif /* TT_STATIC_RASTER */
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth   typedef struct TRaster_Instance_  TRaster_Instance;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth 
349*37da2899SCharles.Forsyth   /* prototypes used for sweep function dispatch */
350*37da2899SCharles.Forsyth   typedef void
351*37da2899SCharles.Forsyth   Function_Sweep_Init( RAS_ARGS Short*  min,
352*37da2899SCharles.Forsyth                                 Short*  max );
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth   typedef void
355*37da2899SCharles.Forsyth   Function_Sweep_Span( RAS_ARGS Short       y,
356*37da2899SCharles.Forsyth                                 FT_F26Dot6  x1,
357*37da2899SCharles.Forsyth                                 FT_F26Dot6  x2,
358*37da2899SCharles.Forsyth                                 PProfile    left,
359*37da2899SCharles.Forsyth                                 PProfile    right );
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth   typedef void
362*37da2899SCharles.Forsyth   Function_Sweep_Step( RAS_ARG );
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth 
365*37da2899SCharles.Forsyth   /* NOTE: These operations are only valid on 2's complement processors */
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth #define FLOOR( x )    ( (x) & -ras.precision )
368*37da2899SCharles.Forsyth #define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
369*37da2899SCharles.Forsyth #define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
370*37da2899SCharles.Forsyth #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
371*37da2899SCharles.Forsyth #define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth   /* Note that I have moved the location of some fields in the */
374*37da2899SCharles.Forsyth   /* structure to ensure that the most used variables are used */
375*37da2899SCharles.Forsyth   /* at the top.  Thus, their offset can be coded with less    */
376*37da2899SCharles.Forsyth   /* opcodes, and it results in a smaller executable.          */
377*37da2899SCharles.Forsyth 
378*37da2899SCharles.Forsyth   struct  TRaster_Instance_
379*37da2899SCharles.Forsyth   {
380*37da2899SCharles.Forsyth     Int       precision_bits;       /* precision related variables         */
381*37da2899SCharles.Forsyth     Int       precision;
382*37da2899SCharles.Forsyth     Int       precision_half;
383*37da2899SCharles.Forsyth     Long      precision_mask;
384*37da2899SCharles.Forsyth     Int       precision_shift;
385*37da2899SCharles.Forsyth     Int       precision_step;
386*37da2899SCharles.Forsyth     Int       precision_jitter;
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth     Int       scale_shift;          /* == precision_shift   for bitmaps    */
389*37da2899SCharles.Forsyth                                     /* == precision_shift+1 for pixmaps    */
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth     PLong     buff;                 /* The profiles buffer                 */
392*37da2899SCharles.Forsyth     PLong     sizeBuff;             /* Render pool size                    */
393*37da2899SCharles.Forsyth     PLong     maxBuff;              /* Profiles buffer size                */
394*37da2899SCharles.Forsyth     PLong     top;                  /* Current cursor in buffer            */
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth     FT_Error  error;
397*37da2899SCharles.Forsyth 
398*37da2899SCharles.Forsyth     Int       numTurns;             /* number of Y-turns in outline        */
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth     TPoint*   arc;                  /* current Bezier arc pointer          */
401*37da2899SCharles.Forsyth 
402*37da2899SCharles.Forsyth     UShort    bWidth;               /* target bitmap width                 */
403*37da2899SCharles.Forsyth     PByte     bTarget;              /* target bitmap buffer                */
404*37da2899SCharles.Forsyth     PByte     gTarget;              /* target pixmap buffer                */
405*37da2899SCharles.Forsyth 
406*37da2899SCharles.Forsyth     Long      lastX, lastY, minY, maxY;
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth     UShort    num_Profs;            /* current number of profiles          */
409*37da2899SCharles.Forsyth 
410*37da2899SCharles.Forsyth     Bool      fresh;                /* signals a fresh new profile which   */
411*37da2899SCharles.Forsyth                                     /* 'start' field must be completed     */
412*37da2899SCharles.Forsyth     Bool      joint;                /* signals that the last arc ended     */
413*37da2899SCharles.Forsyth                                     /* exactly on a scanline.  Allows      */
414*37da2899SCharles.Forsyth                                     /* removal of doublets                 */
415*37da2899SCharles.Forsyth     PProfile  cProfile;             /* current profile                     */
416*37da2899SCharles.Forsyth     PProfile  fProfile;             /* head of linked list of profiles     */
417*37da2899SCharles.Forsyth     PProfile  gProfile;             /* contour's first profile in case     */
418*37da2899SCharles.Forsyth                                     /* of impact                           */
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth     TStates   state;                /* rendering state                     */
421*37da2899SCharles.Forsyth 
422*37da2899SCharles.Forsyth     FT_Bitmap   target;             /* description of target bit/pixmap    */
423*37da2899SCharles.Forsyth     FT_Outline  outline;
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth     Long      traceOfs;             /* current offset in target bitmap     */
426*37da2899SCharles.Forsyth     Long      traceG;               /* current offset in target pixmap     */
427*37da2899SCharles.Forsyth 
428*37da2899SCharles.Forsyth     Short     traceIncr;            /* sweep's increment in target bitmap  */
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth     Short     gray_min_x;           /* current min x during gray rendering */
431*37da2899SCharles.Forsyth     Short     gray_max_x;           /* current max x during gray rendering */
432*37da2899SCharles.Forsyth 
433*37da2899SCharles.Forsyth     /* dispatch variables */
434*37da2899SCharles.Forsyth 
435*37da2899SCharles.Forsyth     Function_Sweep_Init*  Proc_Sweep_Init;
436*37da2899SCharles.Forsyth     Function_Sweep_Span*  Proc_Sweep_Span;
437*37da2899SCharles.Forsyth     Function_Sweep_Span*  Proc_Sweep_Drop;
438*37da2899SCharles.Forsyth     Function_Sweep_Step*  Proc_Sweep_Step;
439*37da2899SCharles.Forsyth 
440*37da2899SCharles.Forsyth     Byte      dropOutControl;       /* current drop_out control method     */
441*37da2899SCharles.Forsyth 
442*37da2899SCharles.Forsyth     Bool      second_pass;          /* indicates wether a horizontal pass  */
443*37da2899SCharles.Forsyth                                     /* should be performed to control      */
444*37da2899SCharles.Forsyth                                     /* drop-out accurately when calling    */
445*37da2899SCharles.Forsyth                                     /* Render_Glyph.  Note that there is   */
446*37da2899SCharles.Forsyth                                     /* no horizontal pass during gray      */
447*37da2899SCharles.Forsyth                                     /* rendering.                          */
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth     TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */
450*37da2899SCharles.Forsyth 
451*37da2899SCharles.Forsyth     TBand     band_stack[16];       /* band stack used for sub-banding     */
452*37da2899SCharles.Forsyth     Int       band_top;             /* band stack top                      */
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth     Int       count_table[256];     /* Look-up table used to quickly count */
455*37da2899SCharles.Forsyth                                     /* set bits in a gray 2x2 cell         */
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth     void*     memory;
458*37da2899SCharles.Forsyth 
459*37da2899SCharles.Forsyth #ifdef FT_RASTER_OPTION_ANTI_ALIASING
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth     Byte      grays[5];             /* Palette of gray levels used for     */
462*37da2899SCharles.Forsyth                                     /* render.                             */
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth     Byte      gray_lines[RASTER_GRAY_LINES];
465*37da2899SCharles.Forsyth                                 /* Intermediate table used to render the   */
466*37da2899SCharles.Forsyth                                 /* graylevels pixmaps.                     */
467*37da2899SCharles.Forsyth                                 /* gray_lines is a buffer holding two      */
468*37da2899SCharles.Forsyth                                 /* monochrome scanlines                    */
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth     Short     gray_width;       /* width in bytes of one monochrome        */
471*37da2899SCharles.Forsyth                                 /* intermediate scanline of gray_lines.    */
472*37da2899SCharles.Forsyth                                 /* Each gray pixel takes 2 bits long there */
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth                        /* The gray_lines must hold 2 lines, thus with size */
475*37da2899SCharles.Forsyth                        /* in bytes of at least `gray_width*2'.             */
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth #endif /* FT_RASTER_ANTI_ALIASING */
478*37da2899SCharles.Forsyth 
479*37da2899SCharles.Forsyth #if 0
480*37da2899SCharles.Forsyth     PByte       flags;              /* current flags table                 */
481*37da2899SCharles.Forsyth     PUShort     outs;               /* current outlines table              */
482*37da2899SCharles.Forsyth     FT_Vector*  coords;
483*37da2899SCharles.Forsyth 
484*37da2899SCharles.Forsyth     UShort      nPoints;            /* number of points in current glyph   */
485*37da2899SCharles.Forsyth     Short       nContours;          /* number of contours in current glyph */
486*37da2899SCharles.Forsyth #endif
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth   };
489*37da2899SCharles.Forsyth 
490*37da2899SCharles.Forsyth 
491*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_STATIC_RASTER
492*37da2899SCharles.Forsyth 
493*37da2899SCharles.Forsyth   static TRaster_Instance  cur_ras;
494*37da2899SCharles.Forsyth #define ras  cur_ras
495*37da2899SCharles.Forsyth 
496*37da2899SCharles.Forsyth #else
497*37da2899SCharles.Forsyth 
498*37da2899SCharles.Forsyth #define ras  (*raster)
499*37da2899SCharles.Forsyth 
500*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_STATIC_RASTER */
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth 
503*37da2899SCharles.Forsyth   /*************************************************************************/
504*37da2899SCharles.Forsyth   /*************************************************************************/
505*37da2899SCharles.Forsyth   /**                                                                     **/
506*37da2899SCharles.Forsyth   /**  PROFILES COMPUTATION                                               **/
507*37da2899SCharles.Forsyth   /**                                                                     **/
508*37da2899SCharles.Forsyth   /*************************************************************************/
509*37da2899SCharles.Forsyth   /*************************************************************************/
510*37da2899SCharles.Forsyth 
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth   /*************************************************************************/
513*37da2899SCharles.Forsyth   /*                                                                       */
514*37da2899SCharles.Forsyth   /* <Function>                                                            */
515*37da2899SCharles.Forsyth   /*    Set_High_Precision                                                 */
516*37da2899SCharles.Forsyth   /*                                                                       */
517*37da2899SCharles.Forsyth   /* <Description>                                                         */
518*37da2899SCharles.Forsyth   /*    Sets precision variables according to param flag.                  */
519*37da2899SCharles.Forsyth   /*                                                                       */
520*37da2899SCharles.Forsyth   /* <Input>                                                               */
521*37da2899SCharles.Forsyth   /*    High :: Set to True for high precision (typically for ppem < 18),  */
522*37da2899SCharles.Forsyth   /*            false otherwise.                                           */
523*37da2899SCharles.Forsyth   /*                                                                       */
524*37da2899SCharles.Forsyth   static void
Set_High_Precision(RAS_ARGS Int High)525*37da2899SCharles.Forsyth   Set_High_Precision( RAS_ARGS Int  High )
526*37da2899SCharles.Forsyth   {
527*37da2899SCharles.Forsyth     if ( High )
528*37da2899SCharles.Forsyth     {
529*37da2899SCharles.Forsyth       ras.precision_bits   = 10;
530*37da2899SCharles.Forsyth       ras.precision_step   = 128;
531*37da2899SCharles.Forsyth       ras.precision_jitter = 24;
532*37da2899SCharles.Forsyth     }
533*37da2899SCharles.Forsyth     else
534*37da2899SCharles.Forsyth     {
535*37da2899SCharles.Forsyth       ras.precision_bits   = 6;
536*37da2899SCharles.Forsyth       ras.precision_step   = 32;
537*37da2899SCharles.Forsyth       ras.precision_jitter = 2;
538*37da2899SCharles.Forsyth     }
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth     FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth     ras.precision       = 1 << ras.precision_bits;
543*37da2899SCharles.Forsyth     ras.precision_half  = ras.precision / 2;
544*37da2899SCharles.Forsyth     ras.precision_shift = ras.precision_bits - Pixel_Bits;
545*37da2899SCharles.Forsyth     ras.precision_mask  = -ras.precision;
546*37da2899SCharles.Forsyth   }
547*37da2899SCharles.Forsyth 
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth   /*************************************************************************/
550*37da2899SCharles.Forsyth   /*                                                                       */
551*37da2899SCharles.Forsyth   /* <Function>                                                            */
552*37da2899SCharles.Forsyth   /*    New_Profile                                                        */
553*37da2899SCharles.Forsyth   /*                                                                       */
554*37da2899SCharles.Forsyth   /* <Description>                                                         */
555*37da2899SCharles.Forsyth   /*    Creates a new profile in the render pool.                          */
556*37da2899SCharles.Forsyth   /*                                                                       */
557*37da2899SCharles.Forsyth   /* <Input>                                                               */
558*37da2899SCharles.Forsyth   /*    aState :: The state/orientation of the new profile.                */
559*37da2899SCharles.Forsyth   /*                                                                       */
560*37da2899SCharles.Forsyth   /* <Return>                                                              */
561*37da2899SCharles.Forsyth   /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
562*37da2899SCharles.Forsyth   /*   profile.                                                            */
563*37da2899SCharles.Forsyth   /*                                                                       */
564*37da2899SCharles.Forsyth   static Bool
New_Profile(RAS_ARGS TStates aState)565*37da2899SCharles.Forsyth   New_Profile( RAS_ARGS TStates  aState )
566*37da2899SCharles.Forsyth   {
567*37da2899SCharles.Forsyth     if ( !ras.fProfile )
568*37da2899SCharles.Forsyth     {
569*37da2899SCharles.Forsyth       ras.cProfile  = (PProfile)ras.top;
570*37da2899SCharles.Forsyth       ras.fProfile  = ras.cProfile;
571*37da2899SCharles.Forsyth       ras.top      += AlignProfileSize;
572*37da2899SCharles.Forsyth     }
573*37da2899SCharles.Forsyth 
574*37da2899SCharles.Forsyth     if ( ras.top >= ras.maxBuff )
575*37da2899SCharles.Forsyth     {
576*37da2899SCharles.Forsyth       ras.error = Raster_Err_Overflow;
577*37da2899SCharles.Forsyth       return FAILURE;
578*37da2899SCharles.Forsyth     }
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth     switch ( aState )
581*37da2899SCharles.Forsyth     {
582*37da2899SCharles.Forsyth     case Ascending_State:
583*37da2899SCharles.Forsyth       ras.cProfile->flow = Flow_Up;
584*37da2899SCharles.Forsyth       FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
585*37da2899SCharles.Forsyth       break;
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth     case Descending_State:
588*37da2899SCharles.Forsyth       ras.cProfile->flow = Flow_Down;
589*37da2899SCharles.Forsyth       FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
590*37da2899SCharles.Forsyth       break;
591*37da2899SCharles.Forsyth 
592*37da2899SCharles.Forsyth     default:
593*37da2899SCharles.Forsyth       FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
594*37da2899SCharles.Forsyth       ras.error = Raster_Err_Invalid;
595*37da2899SCharles.Forsyth       return FAILURE;
596*37da2899SCharles.Forsyth     }
597*37da2899SCharles.Forsyth 
598*37da2899SCharles.Forsyth     ras.cProfile->start  = 0;
599*37da2899SCharles.Forsyth     ras.cProfile->height = 0;
600*37da2899SCharles.Forsyth     ras.cProfile->offset = ras.top;
601*37da2899SCharles.Forsyth     ras.cProfile->link   = (PProfile)0;
602*37da2899SCharles.Forsyth     ras.cProfile->next   = (PProfile)0;
603*37da2899SCharles.Forsyth 
604*37da2899SCharles.Forsyth     if ( !ras.gProfile )
605*37da2899SCharles.Forsyth       ras.gProfile = ras.cProfile;
606*37da2899SCharles.Forsyth 
607*37da2899SCharles.Forsyth     ras.state = aState;
608*37da2899SCharles.Forsyth     ras.fresh = TRUE;
609*37da2899SCharles.Forsyth     ras.joint = FALSE;
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth     return SUCCESS;
612*37da2899SCharles.Forsyth   }
613*37da2899SCharles.Forsyth 
614*37da2899SCharles.Forsyth 
615*37da2899SCharles.Forsyth   /*************************************************************************/
616*37da2899SCharles.Forsyth   /*                                                                       */
617*37da2899SCharles.Forsyth   /* <Function>                                                            */
618*37da2899SCharles.Forsyth   /*    End_Profile                                                        */
619*37da2899SCharles.Forsyth   /*                                                                       */
620*37da2899SCharles.Forsyth   /* <Description>                                                         */
621*37da2899SCharles.Forsyth   /*    Finalizes the current profile.                                     */
622*37da2899SCharles.Forsyth   /*                                                                       */
623*37da2899SCharles.Forsyth   /* <Return>                                                              */
624*37da2899SCharles.Forsyth   /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
625*37da2899SCharles.Forsyth   /*                                                                       */
626*37da2899SCharles.Forsyth   static Bool
End_Profile(RAS_ARG)627*37da2899SCharles.Forsyth   End_Profile( RAS_ARG )
628*37da2899SCharles.Forsyth   {
629*37da2899SCharles.Forsyth     Long      h;
630*37da2899SCharles.Forsyth     PProfile  oldProfile;
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth 
633*37da2899SCharles.Forsyth     h = (Long)( ras.top - ras.cProfile->offset );
634*37da2899SCharles.Forsyth 
635*37da2899SCharles.Forsyth     if ( h < 0 )
636*37da2899SCharles.Forsyth     {
637*37da2899SCharles.Forsyth       FT_ERROR(( "End_Profile: negative height encountered!\n" ));
638*37da2899SCharles.Forsyth       ras.error = Raster_Err_Neg_Height;
639*37da2899SCharles.Forsyth       return FAILURE;
640*37da2899SCharles.Forsyth     }
641*37da2899SCharles.Forsyth 
642*37da2899SCharles.Forsyth     if ( h > 0 )
643*37da2899SCharles.Forsyth     {
644*37da2899SCharles.Forsyth       FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
645*37da2899SCharles.Forsyth                   (long)ras.cProfile, ras.cProfile->start, h ));
646*37da2899SCharles.Forsyth 
647*37da2899SCharles.Forsyth       oldProfile           = ras.cProfile;
648*37da2899SCharles.Forsyth       ras.cProfile->height = h;
649*37da2899SCharles.Forsyth       ras.cProfile         = (PProfile)ras.top;
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth       ras.top             += AlignProfileSize;
652*37da2899SCharles.Forsyth 
653*37da2899SCharles.Forsyth       ras.cProfile->height = 0;
654*37da2899SCharles.Forsyth       ras.cProfile->offset = ras.top;
655*37da2899SCharles.Forsyth       oldProfile->next     = ras.cProfile;
656*37da2899SCharles.Forsyth       ras.num_Profs++;
657*37da2899SCharles.Forsyth     }
658*37da2899SCharles.Forsyth 
659*37da2899SCharles.Forsyth     if ( ras.top >= ras.maxBuff )
660*37da2899SCharles.Forsyth     {
661*37da2899SCharles.Forsyth       FT_TRACE1(( "overflow in End_Profile\n" ));
662*37da2899SCharles.Forsyth       ras.error = Raster_Err_Overflow;
663*37da2899SCharles.Forsyth       return FAILURE;
664*37da2899SCharles.Forsyth     }
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth     ras.joint = FALSE;
667*37da2899SCharles.Forsyth 
668*37da2899SCharles.Forsyth     return SUCCESS;
669*37da2899SCharles.Forsyth   }
670*37da2899SCharles.Forsyth 
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth   /*************************************************************************/
673*37da2899SCharles.Forsyth   /*                                                                       */
674*37da2899SCharles.Forsyth   /* <Function>                                                            */
675*37da2899SCharles.Forsyth   /*    Insert_Y_Turn                                                      */
676*37da2899SCharles.Forsyth   /*                                                                       */
677*37da2899SCharles.Forsyth   /* <Description>                                                         */
678*37da2899SCharles.Forsyth   /*    Inserts a salient into the sorted list placed on top of the render */
679*37da2899SCharles.Forsyth   /*    pool.                                                              */
680*37da2899SCharles.Forsyth   /*                                                                       */
681*37da2899SCharles.Forsyth   /* <Input>                                                               */
682*37da2899SCharles.Forsyth   /*    New y scanline position.                                           */
683*37da2899SCharles.Forsyth   /*                                                                       */
684*37da2899SCharles.Forsyth   /* <Return>                                                              */
685*37da2899SCharles.Forsyth   /*    SUCCESS on success.  FAILURE in case of overflow.                  */
686*37da2899SCharles.Forsyth   /*                                                                       */
687*37da2899SCharles.Forsyth   static Bool
Insert_Y_Turn(RAS_ARGS Int y)688*37da2899SCharles.Forsyth   Insert_Y_Turn( RAS_ARGS Int  y )
689*37da2899SCharles.Forsyth   {
690*37da2899SCharles.Forsyth     PLong     y_turns;
691*37da2899SCharles.Forsyth     Int       y2, n;
692*37da2899SCharles.Forsyth 
693*37da2899SCharles.Forsyth 
694*37da2899SCharles.Forsyth     n       = ras.numTurns - 1;
695*37da2899SCharles.Forsyth     y_turns = ras.sizeBuff - ras.numTurns;
696*37da2899SCharles.Forsyth 
697*37da2899SCharles.Forsyth     /* look for first y value that is <= */
698*37da2899SCharles.Forsyth     while ( n >= 0 && y < y_turns[n] )
699*37da2899SCharles.Forsyth       n--;
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth     /* if it is <, simply insert it, ignore if == */
702*37da2899SCharles.Forsyth     if ( n >= 0 && y > y_turns[n] )
703*37da2899SCharles.Forsyth       while ( n >= 0 )
704*37da2899SCharles.Forsyth       {
705*37da2899SCharles.Forsyth         y2 = (Int)y_turns[n];
706*37da2899SCharles.Forsyth         y_turns[n] = y;
707*37da2899SCharles.Forsyth         y = y2;
708*37da2899SCharles.Forsyth         n--;
709*37da2899SCharles.Forsyth       }
710*37da2899SCharles.Forsyth 
711*37da2899SCharles.Forsyth     if ( n < 0 )
712*37da2899SCharles.Forsyth     {
713*37da2899SCharles.Forsyth       if ( ras.maxBuff <= ras.top )
714*37da2899SCharles.Forsyth       {
715*37da2899SCharles.Forsyth         ras.error = Raster_Err_Overflow;
716*37da2899SCharles.Forsyth         return FAILURE;
717*37da2899SCharles.Forsyth       }
718*37da2899SCharles.Forsyth       ras.maxBuff--;
719*37da2899SCharles.Forsyth       ras.numTurns++;
720*37da2899SCharles.Forsyth       ras.sizeBuff[-ras.numTurns] = y;
721*37da2899SCharles.Forsyth     }
722*37da2899SCharles.Forsyth 
723*37da2899SCharles.Forsyth     return SUCCESS;
724*37da2899SCharles.Forsyth   }
725*37da2899SCharles.Forsyth 
726*37da2899SCharles.Forsyth 
727*37da2899SCharles.Forsyth   /*************************************************************************/
728*37da2899SCharles.Forsyth   /*                                                                       */
729*37da2899SCharles.Forsyth   /* <Function>                                                            */
730*37da2899SCharles.Forsyth   /*    Finalize_Profile_Table                                             */
731*37da2899SCharles.Forsyth   /*                                                                       */
732*37da2899SCharles.Forsyth   /* <Description>                                                         */
733*37da2899SCharles.Forsyth   /*    Adjusts all links in the profiles list.                            */
734*37da2899SCharles.Forsyth   /*                                                                       */
735*37da2899SCharles.Forsyth   /* <Return>                                                              */
736*37da2899SCharles.Forsyth   /*    SUCCESS on success.  FAILURE in case of overflow.                  */
737*37da2899SCharles.Forsyth   /*                                                                       */
738*37da2899SCharles.Forsyth   static Bool
Finalize_Profile_Table(RAS_ARG)739*37da2899SCharles.Forsyth   Finalize_Profile_Table( RAS_ARG )
740*37da2899SCharles.Forsyth   {
741*37da2899SCharles.Forsyth     Int       bottom, top;
742*37da2899SCharles.Forsyth     UShort    n;
743*37da2899SCharles.Forsyth     PProfile  p;
744*37da2899SCharles.Forsyth 
745*37da2899SCharles.Forsyth 
746*37da2899SCharles.Forsyth     n = ras.num_Profs;
747*37da2899SCharles.Forsyth 
748*37da2899SCharles.Forsyth     if ( n > 1 )
749*37da2899SCharles.Forsyth     {
750*37da2899SCharles.Forsyth       p = ras.fProfile;
751*37da2899SCharles.Forsyth       while ( n > 0 )
752*37da2899SCharles.Forsyth       {
753*37da2899SCharles.Forsyth         if ( n > 1 )
754*37da2899SCharles.Forsyth           p->link = (PProfile)( p->offset + p->height );
755*37da2899SCharles.Forsyth         else
756*37da2899SCharles.Forsyth           p->link = NULL;
757*37da2899SCharles.Forsyth 
758*37da2899SCharles.Forsyth         switch ( p->flow )
759*37da2899SCharles.Forsyth         {
760*37da2899SCharles.Forsyth         case Flow_Down:
761*37da2899SCharles.Forsyth           bottom     = (Int)( p->start - p->height + 1 );
762*37da2899SCharles.Forsyth           top        = (Int)p->start;
763*37da2899SCharles.Forsyth           p->start   = bottom;
764*37da2899SCharles.Forsyth           p->offset += p->height - 1;
765*37da2899SCharles.Forsyth           break;
766*37da2899SCharles.Forsyth 
767*37da2899SCharles.Forsyth         case Flow_Up:
768*37da2899SCharles.Forsyth         default:
769*37da2899SCharles.Forsyth           bottom = (Int)p->start;
770*37da2899SCharles.Forsyth           top    = (Int)( p->start + p->height - 1 );
771*37da2899SCharles.Forsyth         }
772*37da2899SCharles.Forsyth 
773*37da2899SCharles.Forsyth         if ( Insert_Y_Turn( RAS_VARS bottom )   ||
774*37da2899SCharles.Forsyth              Insert_Y_Turn( RAS_VARS top + 1 )  )
775*37da2899SCharles.Forsyth           return FAILURE;
776*37da2899SCharles.Forsyth 
777*37da2899SCharles.Forsyth         p = p->link;
778*37da2899SCharles.Forsyth         n--;
779*37da2899SCharles.Forsyth       }
780*37da2899SCharles.Forsyth     }
781*37da2899SCharles.Forsyth     else
782*37da2899SCharles.Forsyth       ras.fProfile = NULL;
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth     return SUCCESS;
785*37da2899SCharles.Forsyth   }
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth 
788*37da2899SCharles.Forsyth   /*************************************************************************/
789*37da2899SCharles.Forsyth   /*                                                                       */
790*37da2899SCharles.Forsyth   /* <Function>                                                            */
791*37da2899SCharles.Forsyth   /*    Split_Conic                                                        */
792*37da2899SCharles.Forsyth   /*                                                                       */
793*37da2899SCharles.Forsyth   /* <Description>                                                         */
794*37da2899SCharles.Forsyth   /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
795*37da2899SCharles.Forsyth   /*    stack.                                                             */
796*37da2899SCharles.Forsyth   /*                                                                       */
797*37da2899SCharles.Forsyth   /* <Input>                                                               */
798*37da2899SCharles.Forsyth   /*    None (subdivided Bezier is taken from the top of the stack).       */
799*37da2899SCharles.Forsyth   /*                                                                       */
800*37da2899SCharles.Forsyth   /* <Note>                                                                */
801*37da2899SCharles.Forsyth   /*    This routine is the `beef' of this component.  It is  _the_ inner  */
802*37da2899SCharles.Forsyth   /*    loop that should be optimized to hell to get the best performance. */
803*37da2899SCharles.Forsyth   /*                                                                       */
804*37da2899SCharles.Forsyth   static void
Split_Conic(TPoint * base)805*37da2899SCharles.Forsyth   Split_Conic( TPoint*  base )
806*37da2899SCharles.Forsyth   {
807*37da2899SCharles.Forsyth     Long  a, b;
808*37da2899SCharles.Forsyth 
809*37da2899SCharles.Forsyth 
810*37da2899SCharles.Forsyth     base[4].x = base[2].x;
811*37da2899SCharles.Forsyth     b = base[1].x;
812*37da2899SCharles.Forsyth     a = base[3].x = ( base[2].x + b ) / 2;
813*37da2899SCharles.Forsyth     b = base[1].x = ( base[0].x + b ) / 2;
814*37da2899SCharles.Forsyth     base[2].x = ( a + b ) / 2;
815*37da2899SCharles.Forsyth 
816*37da2899SCharles.Forsyth     base[4].y = base[2].y;
817*37da2899SCharles.Forsyth     b = base[1].y;
818*37da2899SCharles.Forsyth     a = base[3].y = ( base[2].y + b ) / 2;
819*37da2899SCharles.Forsyth     b = base[1].y = ( base[0].y + b ) / 2;
820*37da2899SCharles.Forsyth     base[2].y = ( a + b ) / 2;
821*37da2899SCharles.Forsyth 
822*37da2899SCharles.Forsyth     /* hand optimized.  gcc doesn't seem to be too good at common      */
823*37da2899SCharles.Forsyth     /* expression substitution and instruction scheduling ;-)          */
824*37da2899SCharles.Forsyth   }
825*37da2899SCharles.Forsyth 
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth   /*************************************************************************/
828*37da2899SCharles.Forsyth   /*                                                                       */
829*37da2899SCharles.Forsyth   /* <Function>                                                            */
830*37da2899SCharles.Forsyth   /*    Split_Cubic                                                        */
831*37da2899SCharles.Forsyth   /*                                                                       */
832*37da2899SCharles.Forsyth   /* <Description>                                                         */
833*37da2899SCharles.Forsyth   /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
834*37da2899SCharles.Forsyth   /*    Bezier stack.                                                      */
835*37da2899SCharles.Forsyth   /*                                                                       */
836*37da2899SCharles.Forsyth   /* <Note>                                                                */
837*37da2899SCharles.Forsyth   /*    This routine is the `beef' of the component.  It is one of _the_   */
838*37da2899SCharles.Forsyth   /*    inner loops that should be optimized like hell to get the best     */
839*37da2899SCharles.Forsyth   /*    performance.                                                       */
840*37da2899SCharles.Forsyth   /*                                                                       */
841*37da2899SCharles.Forsyth   static void
Split_Cubic(TPoint * base)842*37da2899SCharles.Forsyth   Split_Cubic( TPoint*  base )
843*37da2899SCharles.Forsyth   {
844*37da2899SCharles.Forsyth     Long  a, b, c, d;
845*37da2899SCharles.Forsyth 
846*37da2899SCharles.Forsyth 
847*37da2899SCharles.Forsyth     base[6].x = base[3].x;
848*37da2899SCharles.Forsyth     c = base[1].x;
849*37da2899SCharles.Forsyth     d = base[2].x;
850*37da2899SCharles.Forsyth     base[1].x = a = ( base[0].x + c + 1 ) >> 1;
851*37da2899SCharles.Forsyth     base[5].x = b = ( base[3].x + d + 1 ) >> 1;
852*37da2899SCharles.Forsyth     c = ( c + d + 1 ) >> 1;
853*37da2899SCharles.Forsyth     base[2].x = a = ( a + c + 1 ) >> 1;
854*37da2899SCharles.Forsyth     base[4].x = b = ( b + c + 1 ) >> 1;
855*37da2899SCharles.Forsyth     base[3].x = ( a + b + 1 ) >> 1;
856*37da2899SCharles.Forsyth 
857*37da2899SCharles.Forsyth     base[6].y = base[3].y;
858*37da2899SCharles.Forsyth     c = base[1].y;
859*37da2899SCharles.Forsyth     d = base[2].y;
860*37da2899SCharles.Forsyth     base[1].y = a = ( base[0].y + c + 1 ) >> 1;
861*37da2899SCharles.Forsyth     base[5].y = b = ( base[3].y + d + 1 ) >> 1;
862*37da2899SCharles.Forsyth     c = ( c + d + 1 ) >> 1;
863*37da2899SCharles.Forsyth     base[2].y = a = ( a + c + 1 ) >> 1;
864*37da2899SCharles.Forsyth     base[4].y = b = ( b + c + 1 ) >> 1;
865*37da2899SCharles.Forsyth     base[3].y = ( a + b + 1 ) >> 1;
866*37da2899SCharles.Forsyth   }
867*37da2899SCharles.Forsyth 
868*37da2899SCharles.Forsyth 
869*37da2899SCharles.Forsyth   /*************************************************************************/
870*37da2899SCharles.Forsyth   /*                                                                       */
871*37da2899SCharles.Forsyth   /* <Function>                                                            */
872*37da2899SCharles.Forsyth   /*    Line_Up                                                            */
873*37da2899SCharles.Forsyth   /*                                                                       */
874*37da2899SCharles.Forsyth   /* <Description>                                                         */
875*37da2899SCharles.Forsyth   /*    Computes the x-coordinates of an ascending line segment and stores */
876*37da2899SCharles.Forsyth   /*    them in the render pool.                                           */
877*37da2899SCharles.Forsyth   /*                                                                       */
878*37da2899SCharles.Forsyth   /* <Input>                                                               */
879*37da2899SCharles.Forsyth   /*    x1   :: The x-coordinate of the segment's start point.             */
880*37da2899SCharles.Forsyth   /*                                                                       */
881*37da2899SCharles.Forsyth   /*    y1   :: The y-coordinate of the segment's start point.             */
882*37da2899SCharles.Forsyth   /*                                                                       */
883*37da2899SCharles.Forsyth   /*    x2   :: The x-coordinate of the segment's end point.               */
884*37da2899SCharles.Forsyth   /*                                                                       */
885*37da2899SCharles.Forsyth   /*    y2   :: The y-coordinate of the segment's end point.               */
886*37da2899SCharles.Forsyth   /*                                                                       */
887*37da2899SCharles.Forsyth   /*    miny :: A lower vertical clipping bound value.                     */
888*37da2899SCharles.Forsyth   /*                                                                       */
889*37da2899SCharles.Forsyth   /*    maxy :: An upper vertical clipping bound value.                    */
890*37da2899SCharles.Forsyth   /*                                                                       */
891*37da2899SCharles.Forsyth   /* <Return>                                                              */
892*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE on render pool overflow.               */
893*37da2899SCharles.Forsyth   /*                                                                       */
894*37da2899SCharles.Forsyth   static Bool
Line_Up(RAS_ARGS Long x1,Long y1,Long x2,Long y2,Long miny,Long maxy)895*37da2899SCharles.Forsyth   Line_Up( RAS_ARGS Long  x1,
896*37da2899SCharles.Forsyth                     Long  y1,
897*37da2899SCharles.Forsyth                     Long  x2,
898*37da2899SCharles.Forsyth                     Long  y2,
899*37da2899SCharles.Forsyth                     Long  miny,
900*37da2899SCharles.Forsyth                     Long  maxy )
901*37da2899SCharles.Forsyth   {
902*37da2899SCharles.Forsyth     Long   Dx, Dy;
903*37da2899SCharles.Forsyth     Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
904*37da2899SCharles.Forsyth     Long   Ix, Rx, Ax;
905*37da2899SCharles.Forsyth 
906*37da2899SCharles.Forsyth     PLong  top;
907*37da2899SCharles.Forsyth 
908*37da2899SCharles.Forsyth 
909*37da2899SCharles.Forsyth     Dx = x2 - x1;
910*37da2899SCharles.Forsyth     Dy = y2 - y1;
911*37da2899SCharles.Forsyth 
912*37da2899SCharles.Forsyth     if ( Dy <= 0 || y2 < miny || y1 > maxy )
913*37da2899SCharles.Forsyth       return SUCCESS;
914*37da2899SCharles.Forsyth 
915*37da2899SCharles.Forsyth     if ( y1 < miny )
916*37da2899SCharles.Forsyth     {
917*37da2899SCharles.Forsyth       /* Take care: miny-y1 can be a very large value; we use     */
918*37da2899SCharles.Forsyth       /*            a slow MulDiv function to avoid clipping bugs */
919*37da2899SCharles.Forsyth       x1 += SMulDiv( Dx, miny - y1, Dy );
920*37da2899SCharles.Forsyth       e1  = TRUNC( miny );
921*37da2899SCharles.Forsyth       f1  = 0;
922*37da2899SCharles.Forsyth     }
923*37da2899SCharles.Forsyth     else
924*37da2899SCharles.Forsyth     {
925*37da2899SCharles.Forsyth       e1 = (Int)TRUNC( y1 );
926*37da2899SCharles.Forsyth       f1 = (Int)FRAC( y1 );
927*37da2899SCharles.Forsyth     }
928*37da2899SCharles.Forsyth 
929*37da2899SCharles.Forsyth     if ( y2 > maxy )
930*37da2899SCharles.Forsyth     {
931*37da2899SCharles.Forsyth       /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
932*37da2899SCharles.Forsyth       e2  = (Int)TRUNC( maxy );
933*37da2899SCharles.Forsyth       f2  = 0;
934*37da2899SCharles.Forsyth     }
935*37da2899SCharles.Forsyth     else
936*37da2899SCharles.Forsyth     {
937*37da2899SCharles.Forsyth       e2 = (Int)TRUNC( y2 );
938*37da2899SCharles.Forsyth       f2 = (Int)FRAC( y2 );
939*37da2899SCharles.Forsyth     }
940*37da2899SCharles.Forsyth 
941*37da2899SCharles.Forsyth     if ( f1 > 0 )
942*37da2899SCharles.Forsyth     {
943*37da2899SCharles.Forsyth       if ( e1 == e2 )
944*37da2899SCharles.Forsyth         return SUCCESS;
945*37da2899SCharles.Forsyth       else
946*37da2899SCharles.Forsyth       {
947*37da2899SCharles.Forsyth         x1 += FMulDiv( Dx, ras.precision - f1, Dy );
948*37da2899SCharles.Forsyth         e1 += 1;
949*37da2899SCharles.Forsyth       }
950*37da2899SCharles.Forsyth     }
951*37da2899SCharles.Forsyth     else
952*37da2899SCharles.Forsyth       if ( ras.joint )
953*37da2899SCharles.Forsyth       {
954*37da2899SCharles.Forsyth         ras.top--;
955*37da2899SCharles.Forsyth         ras.joint = FALSE;
956*37da2899SCharles.Forsyth       }
957*37da2899SCharles.Forsyth 
958*37da2899SCharles.Forsyth     ras.joint = (char)( f2 == 0 );
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth     if ( ras.fresh )
961*37da2899SCharles.Forsyth     {
962*37da2899SCharles.Forsyth       ras.cProfile->start = e1;
963*37da2899SCharles.Forsyth       ras.fresh           = FALSE;
964*37da2899SCharles.Forsyth     }
965*37da2899SCharles.Forsyth 
966*37da2899SCharles.Forsyth     size = e2 - e1 + 1;
967*37da2899SCharles.Forsyth     if ( ras.top + size >= ras.maxBuff )
968*37da2899SCharles.Forsyth     {
969*37da2899SCharles.Forsyth       ras.error = Raster_Err_Overflow;
970*37da2899SCharles.Forsyth       return FAILURE;
971*37da2899SCharles.Forsyth     }
972*37da2899SCharles.Forsyth 
973*37da2899SCharles.Forsyth     if ( Dx > 0 )
974*37da2899SCharles.Forsyth     {
975*37da2899SCharles.Forsyth       Ix = ( ras.precision * Dx ) / Dy;
976*37da2899SCharles.Forsyth       Rx = ( ras.precision * Dx ) % Dy;
977*37da2899SCharles.Forsyth       Dx = 1;
978*37da2899SCharles.Forsyth     }
979*37da2899SCharles.Forsyth     else
980*37da2899SCharles.Forsyth     {
981*37da2899SCharles.Forsyth       Ix = -( ( ras.precision * -Dx ) / Dy );
982*37da2899SCharles.Forsyth       Rx =    ( ras.precision * -Dx ) % Dy;
983*37da2899SCharles.Forsyth       Dx = -1;
984*37da2899SCharles.Forsyth     }
985*37da2899SCharles.Forsyth 
986*37da2899SCharles.Forsyth     Ax  = -Dy;
987*37da2899SCharles.Forsyth     top = ras.top;
988*37da2899SCharles.Forsyth 
989*37da2899SCharles.Forsyth     while ( size > 0 )
990*37da2899SCharles.Forsyth     {
991*37da2899SCharles.Forsyth       *top++ = x1;
992*37da2899SCharles.Forsyth 
993*37da2899SCharles.Forsyth       x1 += Ix;
994*37da2899SCharles.Forsyth       Ax += Rx;
995*37da2899SCharles.Forsyth       if ( Ax >= 0 )
996*37da2899SCharles.Forsyth       {
997*37da2899SCharles.Forsyth         Ax -= Dy;
998*37da2899SCharles.Forsyth         x1 += Dx;
999*37da2899SCharles.Forsyth       }
1000*37da2899SCharles.Forsyth       size--;
1001*37da2899SCharles.Forsyth     }
1002*37da2899SCharles.Forsyth 
1003*37da2899SCharles.Forsyth     ras.top = top;
1004*37da2899SCharles.Forsyth     return SUCCESS;
1005*37da2899SCharles.Forsyth   }
1006*37da2899SCharles.Forsyth 
1007*37da2899SCharles.Forsyth 
1008*37da2899SCharles.Forsyth   /*************************************************************************/
1009*37da2899SCharles.Forsyth   /*                                                                       */
1010*37da2899SCharles.Forsyth   /* <Function>                                                            */
1011*37da2899SCharles.Forsyth   /*    Line_Down                                                          */
1012*37da2899SCharles.Forsyth   /*                                                                       */
1013*37da2899SCharles.Forsyth   /* <Description>                                                         */
1014*37da2899SCharles.Forsyth   /*    Computes the x-coordinates of an descending line segment and       */
1015*37da2899SCharles.Forsyth   /*    stores them in the render pool.                                    */
1016*37da2899SCharles.Forsyth   /*                                                                       */
1017*37da2899SCharles.Forsyth   /* <Input>                                                               */
1018*37da2899SCharles.Forsyth   /*    x1   :: The x-coordinate of the segment's start point.             */
1019*37da2899SCharles.Forsyth   /*                                                                       */
1020*37da2899SCharles.Forsyth   /*    y1   :: The y-coordinate of the segment's start point.             */
1021*37da2899SCharles.Forsyth   /*                                                                       */
1022*37da2899SCharles.Forsyth   /*    x2   :: The x-coordinate of the segment's end point.               */
1023*37da2899SCharles.Forsyth   /*                                                                       */
1024*37da2899SCharles.Forsyth   /*    y2   :: The y-coordinate of the segment's end point.               */
1025*37da2899SCharles.Forsyth   /*                                                                       */
1026*37da2899SCharles.Forsyth   /*    miny :: A lower vertical clipping bound value.                     */
1027*37da2899SCharles.Forsyth   /*                                                                       */
1028*37da2899SCharles.Forsyth   /*    maxy :: An upper vertical clipping bound value.                    */
1029*37da2899SCharles.Forsyth   /*                                                                       */
1030*37da2899SCharles.Forsyth   /* <Return>                                                              */
1031*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE on render pool overflow.               */
1032*37da2899SCharles.Forsyth   /*                                                                       */
1033*37da2899SCharles.Forsyth   static Bool
Line_Down(RAS_ARGS Long x1,Long y1,Long x2,Long y2,Long miny,Long maxy)1034*37da2899SCharles.Forsyth   Line_Down( RAS_ARGS Long  x1,
1035*37da2899SCharles.Forsyth                       Long  y1,
1036*37da2899SCharles.Forsyth                       Long  x2,
1037*37da2899SCharles.Forsyth                       Long  y2,
1038*37da2899SCharles.Forsyth                       Long  miny,
1039*37da2899SCharles.Forsyth                       Long  maxy )
1040*37da2899SCharles.Forsyth   {
1041*37da2899SCharles.Forsyth     Bool  result, fresh;
1042*37da2899SCharles.Forsyth 
1043*37da2899SCharles.Forsyth 
1044*37da2899SCharles.Forsyth     fresh  = ras.fresh;
1045*37da2899SCharles.Forsyth 
1046*37da2899SCharles.Forsyth     result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1047*37da2899SCharles.Forsyth 
1048*37da2899SCharles.Forsyth     if ( fresh && !ras.fresh )
1049*37da2899SCharles.Forsyth       ras.cProfile->start = -ras.cProfile->start;
1050*37da2899SCharles.Forsyth 
1051*37da2899SCharles.Forsyth     return result;
1052*37da2899SCharles.Forsyth   }
1053*37da2899SCharles.Forsyth 
1054*37da2899SCharles.Forsyth 
1055*37da2899SCharles.Forsyth   /* A function type describing the functions used to split Bezier arcs */
1056*37da2899SCharles.Forsyth   typedef void  (*TSplitter)( TPoint*  base );
1057*37da2899SCharles.Forsyth 
1058*37da2899SCharles.Forsyth 
1059*37da2899SCharles.Forsyth   /*************************************************************************/
1060*37da2899SCharles.Forsyth   /*                                                                       */
1061*37da2899SCharles.Forsyth   /* <Function>                                                            */
1062*37da2899SCharles.Forsyth   /*    Bezier_Up                                                          */
1063*37da2899SCharles.Forsyth   /*                                                                       */
1064*37da2899SCharles.Forsyth   /* <Description>                                                         */
1065*37da2899SCharles.Forsyth   /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
1066*37da2899SCharles.Forsyth   /*    them in the render pool.                                           */
1067*37da2899SCharles.Forsyth   /*                                                                       */
1068*37da2899SCharles.Forsyth   /* <Input>                                                               */
1069*37da2899SCharles.Forsyth   /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1070*37da2899SCharles.Forsyth   /*                                                                       */
1071*37da2899SCharles.Forsyth   /*    splitter :: The function to split Bezier arcs.                     */
1072*37da2899SCharles.Forsyth   /*                                                                       */
1073*37da2899SCharles.Forsyth   /*    miny     :: A lower vertical clipping bound value.                 */
1074*37da2899SCharles.Forsyth   /*                                                                       */
1075*37da2899SCharles.Forsyth   /*    maxy     :: An upper vertical clipping bound value.                */
1076*37da2899SCharles.Forsyth   /*                                                                       */
1077*37da2899SCharles.Forsyth   /* <Return>                                                              */
1078*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE on render pool overflow.               */
1079*37da2899SCharles.Forsyth   /*                                                                       */
1080*37da2899SCharles.Forsyth   static Bool
Bezier_Up(RAS_ARGS Int degree,TSplitter splitter,Long miny,Long maxy)1081*37da2899SCharles.Forsyth   Bezier_Up( RAS_ARGS Int        degree,
1082*37da2899SCharles.Forsyth                       TSplitter  splitter,
1083*37da2899SCharles.Forsyth                       Long       miny,
1084*37da2899SCharles.Forsyth                       Long       maxy )
1085*37da2899SCharles.Forsyth   {
1086*37da2899SCharles.Forsyth     Long   y1, y2, e, e2, e0;
1087*37da2899SCharles.Forsyth     Short  f1;
1088*37da2899SCharles.Forsyth 
1089*37da2899SCharles.Forsyth     TPoint*  arc;
1090*37da2899SCharles.Forsyth     TPoint*  start_arc;
1091*37da2899SCharles.Forsyth 
1092*37da2899SCharles.Forsyth     PLong top;
1093*37da2899SCharles.Forsyth 
1094*37da2899SCharles.Forsyth 
1095*37da2899SCharles.Forsyth     arc = ras.arc;
1096*37da2899SCharles.Forsyth     y1  = arc[degree].y;
1097*37da2899SCharles.Forsyth     y2  = arc[0].y;
1098*37da2899SCharles.Forsyth     top = ras.top;
1099*37da2899SCharles.Forsyth 
1100*37da2899SCharles.Forsyth     if ( y2 < miny || y1 > maxy )
1101*37da2899SCharles.Forsyth       goto Fin;
1102*37da2899SCharles.Forsyth 
1103*37da2899SCharles.Forsyth     e2 = FLOOR( y2 );
1104*37da2899SCharles.Forsyth 
1105*37da2899SCharles.Forsyth     if ( e2 > maxy )
1106*37da2899SCharles.Forsyth       e2 = maxy;
1107*37da2899SCharles.Forsyth 
1108*37da2899SCharles.Forsyth     e0 = miny;
1109*37da2899SCharles.Forsyth 
1110*37da2899SCharles.Forsyth     if ( y1 < miny )
1111*37da2899SCharles.Forsyth       e = miny;
1112*37da2899SCharles.Forsyth     else
1113*37da2899SCharles.Forsyth     {
1114*37da2899SCharles.Forsyth       e  = CEILING( y1 );
1115*37da2899SCharles.Forsyth       f1 = (Short)( FRAC( y1 ) );
1116*37da2899SCharles.Forsyth       e0 = e;
1117*37da2899SCharles.Forsyth 
1118*37da2899SCharles.Forsyth       if ( f1 == 0 )
1119*37da2899SCharles.Forsyth       {
1120*37da2899SCharles.Forsyth         if ( ras.joint )
1121*37da2899SCharles.Forsyth         {
1122*37da2899SCharles.Forsyth           top--;
1123*37da2899SCharles.Forsyth           ras.joint = FALSE;
1124*37da2899SCharles.Forsyth         }
1125*37da2899SCharles.Forsyth 
1126*37da2899SCharles.Forsyth         *top++ = arc[degree].x;
1127*37da2899SCharles.Forsyth 
1128*37da2899SCharles.Forsyth         e += ras.precision;
1129*37da2899SCharles.Forsyth       }
1130*37da2899SCharles.Forsyth     }
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth     if ( ras.fresh )
1133*37da2899SCharles.Forsyth     {
1134*37da2899SCharles.Forsyth       ras.cProfile->start = TRUNC( e0 );
1135*37da2899SCharles.Forsyth       ras.fresh = FALSE;
1136*37da2899SCharles.Forsyth     }
1137*37da2899SCharles.Forsyth 
1138*37da2899SCharles.Forsyth     if ( e2 < e )
1139*37da2899SCharles.Forsyth       goto Fin;
1140*37da2899SCharles.Forsyth 
1141*37da2899SCharles.Forsyth     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1142*37da2899SCharles.Forsyth     {
1143*37da2899SCharles.Forsyth       ras.top   = top;
1144*37da2899SCharles.Forsyth       ras.error = Raster_Err_Overflow;
1145*37da2899SCharles.Forsyth       return FAILURE;
1146*37da2899SCharles.Forsyth     }
1147*37da2899SCharles.Forsyth 
1148*37da2899SCharles.Forsyth     start_arc = arc;
1149*37da2899SCharles.Forsyth 
1150*37da2899SCharles.Forsyth     while ( arc >= start_arc && e <= e2 )
1151*37da2899SCharles.Forsyth     {
1152*37da2899SCharles.Forsyth       ras.joint = FALSE;
1153*37da2899SCharles.Forsyth 
1154*37da2899SCharles.Forsyth       y2 = arc[0].y;
1155*37da2899SCharles.Forsyth 
1156*37da2899SCharles.Forsyth       if ( y2 > e )
1157*37da2899SCharles.Forsyth       {
1158*37da2899SCharles.Forsyth         y1 = arc[degree].y;
1159*37da2899SCharles.Forsyth         if ( y2 - y1 >= ras.precision_step )
1160*37da2899SCharles.Forsyth         {
1161*37da2899SCharles.Forsyth           splitter( arc );
1162*37da2899SCharles.Forsyth           arc += degree;
1163*37da2899SCharles.Forsyth         }
1164*37da2899SCharles.Forsyth         else
1165*37da2899SCharles.Forsyth         {
1166*37da2899SCharles.Forsyth           *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
1167*37da2899SCharles.Forsyth                                             e - y1, y2 - y1 );
1168*37da2899SCharles.Forsyth           arc -= degree;
1169*37da2899SCharles.Forsyth           e   += ras.precision;
1170*37da2899SCharles.Forsyth         }
1171*37da2899SCharles.Forsyth       }
1172*37da2899SCharles.Forsyth       else
1173*37da2899SCharles.Forsyth       {
1174*37da2899SCharles.Forsyth         if ( y2 == e )
1175*37da2899SCharles.Forsyth         {
1176*37da2899SCharles.Forsyth           ras.joint  = TRUE;
1177*37da2899SCharles.Forsyth           *top++     = arc[0].x;
1178*37da2899SCharles.Forsyth 
1179*37da2899SCharles.Forsyth           e += ras.precision;
1180*37da2899SCharles.Forsyth         }
1181*37da2899SCharles.Forsyth         arc -= degree;
1182*37da2899SCharles.Forsyth       }
1183*37da2899SCharles.Forsyth     }
1184*37da2899SCharles.Forsyth 
1185*37da2899SCharles.Forsyth   Fin:
1186*37da2899SCharles.Forsyth     ras.top  = top;
1187*37da2899SCharles.Forsyth     ras.arc -= degree;
1188*37da2899SCharles.Forsyth     return SUCCESS;
1189*37da2899SCharles.Forsyth   }
1190*37da2899SCharles.Forsyth 
1191*37da2899SCharles.Forsyth 
1192*37da2899SCharles.Forsyth   /*************************************************************************/
1193*37da2899SCharles.Forsyth   /*                                                                       */
1194*37da2899SCharles.Forsyth   /* <Function>                                                            */
1195*37da2899SCharles.Forsyth   /*    Bezier_Down                                                        */
1196*37da2899SCharles.Forsyth   /*                                                                       */
1197*37da2899SCharles.Forsyth   /* <Description>                                                         */
1198*37da2899SCharles.Forsyth   /*    Computes the x-coordinates of an descending Bezier arc and stores  */
1199*37da2899SCharles.Forsyth   /*    them in the render pool.                                           */
1200*37da2899SCharles.Forsyth   /*                                                                       */
1201*37da2899SCharles.Forsyth   /* <Input>                                                               */
1202*37da2899SCharles.Forsyth   /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1203*37da2899SCharles.Forsyth   /*                                                                       */
1204*37da2899SCharles.Forsyth   /*    splitter :: The function to split Bezier arcs.                     */
1205*37da2899SCharles.Forsyth   /*                                                                       */
1206*37da2899SCharles.Forsyth   /*    miny     :: A lower vertical clipping bound value.                 */
1207*37da2899SCharles.Forsyth   /*                                                                       */
1208*37da2899SCharles.Forsyth   /*    maxy     :: An upper vertical clipping bound value.                */
1209*37da2899SCharles.Forsyth   /*                                                                       */
1210*37da2899SCharles.Forsyth   /* <Return>                                                              */
1211*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE on render pool overflow.               */
1212*37da2899SCharles.Forsyth   /*                                                                       */
1213*37da2899SCharles.Forsyth   static Bool
Bezier_Down(RAS_ARGS Int degree,TSplitter splitter,Long miny,Long maxy)1214*37da2899SCharles.Forsyth   Bezier_Down( RAS_ARGS Int        degree,
1215*37da2899SCharles.Forsyth                         TSplitter  splitter,
1216*37da2899SCharles.Forsyth                         Long       miny,
1217*37da2899SCharles.Forsyth                         Long       maxy )
1218*37da2899SCharles.Forsyth   {
1219*37da2899SCharles.Forsyth     TPoint*  arc = ras.arc;
1220*37da2899SCharles.Forsyth     Bool     result, fresh;
1221*37da2899SCharles.Forsyth 
1222*37da2899SCharles.Forsyth 
1223*37da2899SCharles.Forsyth     arc[0].y = -arc[0].y;
1224*37da2899SCharles.Forsyth     arc[1].y = -arc[1].y;
1225*37da2899SCharles.Forsyth     arc[2].y = -arc[2].y;
1226*37da2899SCharles.Forsyth     if ( degree > 2 )
1227*37da2899SCharles.Forsyth       arc[3].y = -arc[3].y;
1228*37da2899SCharles.Forsyth 
1229*37da2899SCharles.Forsyth     fresh = ras.fresh;
1230*37da2899SCharles.Forsyth 
1231*37da2899SCharles.Forsyth     result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1232*37da2899SCharles.Forsyth 
1233*37da2899SCharles.Forsyth     if ( fresh && !ras.fresh )
1234*37da2899SCharles.Forsyth       ras.cProfile->start = -ras.cProfile->start;
1235*37da2899SCharles.Forsyth 
1236*37da2899SCharles.Forsyth     arc[0].y = -arc[0].y;
1237*37da2899SCharles.Forsyth     return result;
1238*37da2899SCharles.Forsyth   }
1239*37da2899SCharles.Forsyth 
1240*37da2899SCharles.Forsyth 
1241*37da2899SCharles.Forsyth   /*************************************************************************/
1242*37da2899SCharles.Forsyth   /*                                                                       */
1243*37da2899SCharles.Forsyth   /* <Function>                                                            */
1244*37da2899SCharles.Forsyth   /*    Line_To                                                            */
1245*37da2899SCharles.Forsyth   /*                                                                       */
1246*37da2899SCharles.Forsyth   /* <Description>                                                         */
1247*37da2899SCharles.Forsyth   /*    Injects a new line segment and adjusts Profiles list.              */
1248*37da2899SCharles.Forsyth   /*                                                                       */
1249*37da2899SCharles.Forsyth   /* <Input>                                                               */
1250*37da2899SCharles.Forsyth   /*   x :: The x-coordinate of the segment's end point (its start point   */
1251*37da2899SCharles.Forsyth   /*        is stored in `LastX').                                         */
1252*37da2899SCharles.Forsyth   /*                                                                       */
1253*37da2899SCharles.Forsyth   /*   y :: The y-coordinate of the segment's end point (its start point   */
1254*37da2899SCharles.Forsyth   /*        is stored in `LastY').                                         */
1255*37da2899SCharles.Forsyth   /*                                                                       */
1256*37da2899SCharles.Forsyth   /* <Return>                                                              */
1257*37da2899SCharles.Forsyth   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1258*37da2899SCharles.Forsyth   /*   profile.                                                            */
1259*37da2899SCharles.Forsyth   /*                                                                       */
1260*37da2899SCharles.Forsyth   static Bool
Line_To(RAS_ARGS Long x,Long y)1261*37da2899SCharles.Forsyth   Line_To( RAS_ARGS Long  x,
1262*37da2899SCharles.Forsyth                     Long  y )
1263*37da2899SCharles.Forsyth   {
1264*37da2899SCharles.Forsyth     /* First, detect a change of direction */
1265*37da2899SCharles.Forsyth 
1266*37da2899SCharles.Forsyth     switch ( ras.state )
1267*37da2899SCharles.Forsyth     {
1268*37da2899SCharles.Forsyth     case Unknown_State:
1269*37da2899SCharles.Forsyth       if ( y > ras.lastY )
1270*37da2899SCharles.Forsyth       {
1271*37da2899SCharles.Forsyth         if ( New_Profile( RAS_VARS Ascending_State ) )
1272*37da2899SCharles.Forsyth           return FAILURE;
1273*37da2899SCharles.Forsyth       }
1274*37da2899SCharles.Forsyth       else
1275*37da2899SCharles.Forsyth       {
1276*37da2899SCharles.Forsyth         if ( y < ras.lastY )
1277*37da2899SCharles.Forsyth           if ( New_Profile( RAS_VARS Descending_State ) )
1278*37da2899SCharles.Forsyth             return FAILURE;
1279*37da2899SCharles.Forsyth       }
1280*37da2899SCharles.Forsyth       break;
1281*37da2899SCharles.Forsyth 
1282*37da2899SCharles.Forsyth     case Ascending_State:
1283*37da2899SCharles.Forsyth       if ( y < ras.lastY )
1284*37da2899SCharles.Forsyth       {
1285*37da2899SCharles.Forsyth         if ( End_Profile( RAS_VAR )                   ||
1286*37da2899SCharles.Forsyth              New_Profile( RAS_VARS Descending_State ) )
1287*37da2899SCharles.Forsyth           return FAILURE;
1288*37da2899SCharles.Forsyth       }
1289*37da2899SCharles.Forsyth       break;
1290*37da2899SCharles.Forsyth 
1291*37da2899SCharles.Forsyth     case Descending_State:
1292*37da2899SCharles.Forsyth       if ( y > ras.lastY )
1293*37da2899SCharles.Forsyth       {
1294*37da2899SCharles.Forsyth         if ( End_Profile( RAS_VAR )                  ||
1295*37da2899SCharles.Forsyth              New_Profile( RAS_VARS Ascending_State ) )
1296*37da2899SCharles.Forsyth           return FAILURE;
1297*37da2899SCharles.Forsyth       }
1298*37da2899SCharles.Forsyth       break;
1299*37da2899SCharles.Forsyth 
1300*37da2899SCharles.Forsyth     default:
1301*37da2899SCharles.Forsyth       ;
1302*37da2899SCharles.Forsyth     }
1303*37da2899SCharles.Forsyth 
1304*37da2899SCharles.Forsyth     /* Then compute the lines */
1305*37da2899SCharles.Forsyth 
1306*37da2899SCharles.Forsyth     switch ( ras.state )
1307*37da2899SCharles.Forsyth     {
1308*37da2899SCharles.Forsyth     case Ascending_State:
1309*37da2899SCharles.Forsyth       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
1310*37da2899SCharles.Forsyth                     x, y, ras.minY, ras.maxY ) )
1311*37da2899SCharles.Forsyth         return FAILURE;
1312*37da2899SCharles.Forsyth       break;
1313*37da2899SCharles.Forsyth 
1314*37da2899SCharles.Forsyth     case Descending_State:
1315*37da2899SCharles.Forsyth       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
1316*37da2899SCharles.Forsyth                       x, y, ras.minY, ras.maxY ) )
1317*37da2899SCharles.Forsyth         return FAILURE;
1318*37da2899SCharles.Forsyth       break;
1319*37da2899SCharles.Forsyth 
1320*37da2899SCharles.Forsyth     default:
1321*37da2899SCharles.Forsyth       ;
1322*37da2899SCharles.Forsyth     }
1323*37da2899SCharles.Forsyth 
1324*37da2899SCharles.Forsyth     ras.lastX = x;
1325*37da2899SCharles.Forsyth     ras.lastY = y;
1326*37da2899SCharles.Forsyth 
1327*37da2899SCharles.Forsyth     return SUCCESS;
1328*37da2899SCharles.Forsyth   }
1329*37da2899SCharles.Forsyth 
1330*37da2899SCharles.Forsyth 
1331*37da2899SCharles.Forsyth   /*************************************************************************/
1332*37da2899SCharles.Forsyth   /*                                                                       */
1333*37da2899SCharles.Forsyth   /* <Function>                                                            */
1334*37da2899SCharles.Forsyth   /*    Conic_To                                                           */
1335*37da2899SCharles.Forsyth   /*                                                                       */
1336*37da2899SCharles.Forsyth   /* <Description>                                                         */
1337*37da2899SCharles.Forsyth   /*    Injects a new conic arc and adjusts the profile list.              */
1338*37da2899SCharles.Forsyth   /*                                                                       */
1339*37da2899SCharles.Forsyth   /* <Input>                                                               */
1340*37da2899SCharles.Forsyth   /*   cx :: The x-coordinate of the arc's new control point.              */
1341*37da2899SCharles.Forsyth   /*                                                                       */
1342*37da2899SCharles.Forsyth   /*   cy :: The y-coordinate of the arc's new control point.              */
1343*37da2899SCharles.Forsyth   /*                                                                       */
1344*37da2899SCharles.Forsyth   /*   x  :: The x-coordinate of the arc's end point (its start point is   */
1345*37da2899SCharles.Forsyth   /*         stored in `LastX').                                           */
1346*37da2899SCharles.Forsyth   /*                                                                       */
1347*37da2899SCharles.Forsyth   /*   y  :: The y-coordinate of the arc's end point (its start point is   */
1348*37da2899SCharles.Forsyth   /*         stored in `LastY').                                           */
1349*37da2899SCharles.Forsyth   /*                                                                       */
1350*37da2899SCharles.Forsyth   /* <Return>                                                              */
1351*37da2899SCharles.Forsyth   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1352*37da2899SCharles.Forsyth   /*   profile.                                                            */
1353*37da2899SCharles.Forsyth   /*                                                                       */
1354*37da2899SCharles.Forsyth   static Bool
Conic_To(RAS_ARGS Long cx,Long cy,Long x,Long y)1355*37da2899SCharles.Forsyth   Conic_To( RAS_ARGS Long  cx,
1356*37da2899SCharles.Forsyth                      Long  cy,
1357*37da2899SCharles.Forsyth                      Long  x,
1358*37da2899SCharles.Forsyth                      Long  y )
1359*37da2899SCharles.Forsyth   {
1360*37da2899SCharles.Forsyth     Long     y1, y2, y3, x3, ymin, ymax;
1361*37da2899SCharles.Forsyth     TStates  state_bez;
1362*37da2899SCharles.Forsyth 
1363*37da2899SCharles.Forsyth 
1364*37da2899SCharles.Forsyth     ras.arc      = ras.arcs;
1365*37da2899SCharles.Forsyth     ras.arc[2].x = ras.lastX;
1366*37da2899SCharles.Forsyth     ras.arc[2].y = ras.lastY;
1367*37da2899SCharles.Forsyth     ras.arc[1].x = cx; ras.arc[1].y = cy;
1368*37da2899SCharles.Forsyth     ras.arc[0].x = x;  ras.arc[0].y = y;
1369*37da2899SCharles.Forsyth 
1370*37da2899SCharles.Forsyth     do
1371*37da2899SCharles.Forsyth     {
1372*37da2899SCharles.Forsyth       y1 = ras.arc[2].y;
1373*37da2899SCharles.Forsyth       y2 = ras.arc[1].y;
1374*37da2899SCharles.Forsyth       y3 = ras.arc[0].y;
1375*37da2899SCharles.Forsyth       x3 = ras.arc[0].x;
1376*37da2899SCharles.Forsyth 
1377*37da2899SCharles.Forsyth       /* first, categorize the Bezier arc */
1378*37da2899SCharles.Forsyth 
1379*37da2899SCharles.Forsyth       if ( y1 <= y3 )
1380*37da2899SCharles.Forsyth       {
1381*37da2899SCharles.Forsyth         ymin = y1;
1382*37da2899SCharles.Forsyth         ymax = y3;
1383*37da2899SCharles.Forsyth       }
1384*37da2899SCharles.Forsyth       else
1385*37da2899SCharles.Forsyth       {
1386*37da2899SCharles.Forsyth         ymin = y3;
1387*37da2899SCharles.Forsyth         ymax = y1;
1388*37da2899SCharles.Forsyth       }
1389*37da2899SCharles.Forsyth 
1390*37da2899SCharles.Forsyth       if ( y2 < ymin || y2 > ymax )
1391*37da2899SCharles.Forsyth       {
1392*37da2899SCharles.Forsyth         /* this arc has no given direction, split it! */
1393*37da2899SCharles.Forsyth         Split_Conic( ras.arc );
1394*37da2899SCharles.Forsyth         ras.arc += 2;
1395*37da2899SCharles.Forsyth       }
1396*37da2899SCharles.Forsyth       else if ( y1 == y3 )
1397*37da2899SCharles.Forsyth       {
1398*37da2899SCharles.Forsyth         /* this arc is flat, ignore it and pop it from the Bezier stack */
1399*37da2899SCharles.Forsyth         ras.arc -= 2;
1400*37da2899SCharles.Forsyth       }
1401*37da2899SCharles.Forsyth       else
1402*37da2899SCharles.Forsyth       {
1403*37da2899SCharles.Forsyth         /* the arc is y-monotonous, either ascending or descending */
1404*37da2899SCharles.Forsyth         /* detect a change of direction                            */
1405*37da2899SCharles.Forsyth         state_bez = y1 < y3 ? Ascending_State : Descending_State;
1406*37da2899SCharles.Forsyth         if ( ras.state != state_bez )
1407*37da2899SCharles.Forsyth         {
1408*37da2899SCharles.Forsyth           /* finalize current profile if any */
1409*37da2899SCharles.Forsyth           if ( ras.state != Unknown_State   &&
1410*37da2899SCharles.Forsyth                End_Profile( RAS_VAR ) )
1411*37da2899SCharles.Forsyth             goto Fail;
1412*37da2899SCharles.Forsyth 
1413*37da2899SCharles.Forsyth           /* create a new profile */
1414*37da2899SCharles.Forsyth           if ( New_Profile( RAS_VARS state_bez ) )
1415*37da2899SCharles.Forsyth             goto Fail;
1416*37da2899SCharles.Forsyth         }
1417*37da2899SCharles.Forsyth 
1418*37da2899SCharles.Forsyth         /* now call the appropriate routine */
1419*37da2899SCharles.Forsyth         if ( state_bez == Ascending_State )
1420*37da2899SCharles.Forsyth         {
1421*37da2899SCharles.Forsyth           if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1422*37da2899SCharles.Forsyth             goto Fail;
1423*37da2899SCharles.Forsyth         }
1424*37da2899SCharles.Forsyth         else
1425*37da2899SCharles.Forsyth           if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1426*37da2899SCharles.Forsyth             goto Fail;
1427*37da2899SCharles.Forsyth       }
1428*37da2899SCharles.Forsyth 
1429*37da2899SCharles.Forsyth     } while ( ras.arc >= ras.arcs );
1430*37da2899SCharles.Forsyth 
1431*37da2899SCharles.Forsyth     ras.lastX = x3;
1432*37da2899SCharles.Forsyth     ras.lastY = y3;
1433*37da2899SCharles.Forsyth 
1434*37da2899SCharles.Forsyth     return SUCCESS;
1435*37da2899SCharles.Forsyth 
1436*37da2899SCharles.Forsyth   Fail:
1437*37da2899SCharles.Forsyth     return FAILURE;
1438*37da2899SCharles.Forsyth   }
1439*37da2899SCharles.Forsyth 
1440*37da2899SCharles.Forsyth 
1441*37da2899SCharles.Forsyth   /*************************************************************************/
1442*37da2899SCharles.Forsyth   /*                                                                       */
1443*37da2899SCharles.Forsyth   /* <Function>                                                            */
1444*37da2899SCharles.Forsyth   /*    Cubic_To                                                           */
1445*37da2899SCharles.Forsyth   /*                                                                       */
1446*37da2899SCharles.Forsyth   /* <Description>                                                         */
1447*37da2899SCharles.Forsyth   /*    Injects a new cubic arc and adjusts the profile list.              */
1448*37da2899SCharles.Forsyth   /*                                                                       */
1449*37da2899SCharles.Forsyth   /* <Input>                                                               */
1450*37da2899SCharles.Forsyth   /*   cx1 :: The x-coordinate of the arc's first new control point.       */
1451*37da2899SCharles.Forsyth   /*                                                                       */
1452*37da2899SCharles.Forsyth   /*   cy1 :: The y-coordinate of the arc's first new control point.       */
1453*37da2899SCharles.Forsyth   /*                                                                       */
1454*37da2899SCharles.Forsyth   /*   cx2 :: The x-coordinate of the arc's second new control point.      */
1455*37da2899SCharles.Forsyth   /*                                                                       */
1456*37da2899SCharles.Forsyth   /*   cy2 :: The y-coordinate of the arc's second new control point.      */
1457*37da2899SCharles.Forsyth   /*                                                                       */
1458*37da2899SCharles.Forsyth   /*   x   :: The x-coordinate of the arc's end point (its start point is  */
1459*37da2899SCharles.Forsyth   /*          stored in `LastX').                                          */
1460*37da2899SCharles.Forsyth   /*                                                                       */
1461*37da2899SCharles.Forsyth   /*   y   :: The y-coordinate of the arc's end point (its start point is  */
1462*37da2899SCharles.Forsyth   /*          stored in `LastY').                                          */
1463*37da2899SCharles.Forsyth   /*                                                                       */
1464*37da2899SCharles.Forsyth   /* <Return>                                                              */
1465*37da2899SCharles.Forsyth   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1466*37da2899SCharles.Forsyth   /*   profile.                                                            */
1467*37da2899SCharles.Forsyth   /*                                                                       */
1468*37da2899SCharles.Forsyth   static Bool
Cubic_To(RAS_ARGS Long cx1,Long cy1,Long cx2,Long cy2,Long x,Long y)1469*37da2899SCharles.Forsyth   Cubic_To( RAS_ARGS Long  cx1,
1470*37da2899SCharles.Forsyth                      Long  cy1,
1471*37da2899SCharles.Forsyth                      Long  cx2,
1472*37da2899SCharles.Forsyth                      Long  cy2,
1473*37da2899SCharles.Forsyth                      Long  x,
1474*37da2899SCharles.Forsyth                      Long  y )
1475*37da2899SCharles.Forsyth   {
1476*37da2899SCharles.Forsyth     Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1477*37da2899SCharles.Forsyth     TStates  state_bez;
1478*37da2899SCharles.Forsyth 
1479*37da2899SCharles.Forsyth 
1480*37da2899SCharles.Forsyth     ras.arc      = ras.arcs;
1481*37da2899SCharles.Forsyth     ras.arc[3].x = ras.lastX;
1482*37da2899SCharles.Forsyth     ras.arc[3].y = ras.lastY;
1483*37da2899SCharles.Forsyth     ras.arc[2].x = cx1; ras.arc[2].y = cy1;
1484*37da2899SCharles.Forsyth     ras.arc[1].x = cx2; ras.arc[1].y = cy2;
1485*37da2899SCharles.Forsyth     ras.arc[0].x = x;   ras.arc[0].y = y;
1486*37da2899SCharles.Forsyth 
1487*37da2899SCharles.Forsyth     do
1488*37da2899SCharles.Forsyth     {
1489*37da2899SCharles.Forsyth       y1 = ras.arc[3].y;
1490*37da2899SCharles.Forsyth       y2 = ras.arc[2].y;
1491*37da2899SCharles.Forsyth       y3 = ras.arc[1].y;
1492*37da2899SCharles.Forsyth       y4 = ras.arc[0].y;
1493*37da2899SCharles.Forsyth       x4 = ras.arc[0].x;
1494*37da2899SCharles.Forsyth 
1495*37da2899SCharles.Forsyth       /* first, categorize the Bezier arc */
1496*37da2899SCharles.Forsyth 
1497*37da2899SCharles.Forsyth       if ( y1 <= y4 )
1498*37da2899SCharles.Forsyth       {
1499*37da2899SCharles.Forsyth         ymin1 = y1;
1500*37da2899SCharles.Forsyth         ymax1 = y4;
1501*37da2899SCharles.Forsyth       }
1502*37da2899SCharles.Forsyth       else
1503*37da2899SCharles.Forsyth       {
1504*37da2899SCharles.Forsyth         ymin1 = y4;
1505*37da2899SCharles.Forsyth         ymax1 = y1;
1506*37da2899SCharles.Forsyth       }
1507*37da2899SCharles.Forsyth 
1508*37da2899SCharles.Forsyth       if ( y2 <= y3 )
1509*37da2899SCharles.Forsyth       {
1510*37da2899SCharles.Forsyth         ymin2 = y2;
1511*37da2899SCharles.Forsyth         ymax2 = y3;
1512*37da2899SCharles.Forsyth       }
1513*37da2899SCharles.Forsyth       else
1514*37da2899SCharles.Forsyth       {
1515*37da2899SCharles.Forsyth         ymin2 = y3;
1516*37da2899SCharles.Forsyth         ymax2 = y2;
1517*37da2899SCharles.Forsyth       }
1518*37da2899SCharles.Forsyth 
1519*37da2899SCharles.Forsyth       if ( ymin2 < ymin1 || ymax2 > ymax1 )
1520*37da2899SCharles.Forsyth       {
1521*37da2899SCharles.Forsyth         /* this arc has no given direction, split it! */
1522*37da2899SCharles.Forsyth         Split_Cubic( ras.arc );
1523*37da2899SCharles.Forsyth         ras.arc += 3;
1524*37da2899SCharles.Forsyth       }
1525*37da2899SCharles.Forsyth       else if ( y1 == y4 )
1526*37da2899SCharles.Forsyth       {
1527*37da2899SCharles.Forsyth         /* this arc is flat, ignore it and pop it from the Bezier stack */
1528*37da2899SCharles.Forsyth         ras.arc -= 3;
1529*37da2899SCharles.Forsyth       }
1530*37da2899SCharles.Forsyth       else
1531*37da2899SCharles.Forsyth       {
1532*37da2899SCharles.Forsyth         state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1533*37da2899SCharles.Forsyth 
1534*37da2899SCharles.Forsyth         /* detect a change of direction */
1535*37da2899SCharles.Forsyth         if ( ras.state != state_bez )
1536*37da2899SCharles.Forsyth         {
1537*37da2899SCharles.Forsyth           if ( ras.state != Unknown_State   &&
1538*37da2899SCharles.Forsyth                End_Profile( RAS_VAR ) )
1539*37da2899SCharles.Forsyth             goto Fail;
1540*37da2899SCharles.Forsyth 
1541*37da2899SCharles.Forsyth           if ( New_Profile( RAS_VARS state_bez ) )
1542*37da2899SCharles.Forsyth             goto Fail;
1543*37da2899SCharles.Forsyth         }
1544*37da2899SCharles.Forsyth 
1545*37da2899SCharles.Forsyth         /* compute intersections */
1546*37da2899SCharles.Forsyth         if ( state_bez == Ascending_State )
1547*37da2899SCharles.Forsyth         {
1548*37da2899SCharles.Forsyth           if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1549*37da2899SCharles.Forsyth             goto Fail;
1550*37da2899SCharles.Forsyth         }
1551*37da2899SCharles.Forsyth         else
1552*37da2899SCharles.Forsyth           if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1553*37da2899SCharles.Forsyth             goto Fail;
1554*37da2899SCharles.Forsyth       }
1555*37da2899SCharles.Forsyth 
1556*37da2899SCharles.Forsyth     } while ( ras.arc >= ras.arcs );
1557*37da2899SCharles.Forsyth 
1558*37da2899SCharles.Forsyth     ras.lastX = x4;
1559*37da2899SCharles.Forsyth     ras.lastY = y4;
1560*37da2899SCharles.Forsyth 
1561*37da2899SCharles.Forsyth     return SUCCESS;
1562*37da2899SCharles.Forsyth 
1563*37da2899SCharles.Forsyth   Fail:
1564*37da2899SCharles.Forsyth     return FAILURE;
1565*37da2899SCharles.Forsyth   }
1566*37da2899SCharles.Forsyth 
1567*37da2899SCharles.Forsyth 
1568*37da2899SCharles.Forsyth #undef  SWAP_
1569*37da2899SCharles.Forsyth #define SWAP_( x, y )  do                \
1570*37da2899SCharles.Forsyth                        {                 \
1571*37da2899SCharles.Forsyth                          Long  swap = x; \
1572*37da2899SCharles.Forsyth                                          \
1573*37da2899SCharles.Forsyth                                          \
1574*37da2899SCharles.Forsyth                          x = y;          \
1575*37da2899SCharles.Forsyth                          y = swap;       \
1576*37da2899SCharles.Forsyth                        } while ( 0 )
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth 
1579*37da2899SCharles.Forsyth   /*************************************************************************/
1580*37da2899SCharles.Forsyth   /*                                                                       */
1581*37da2899SCharles.Forsyth   /* <Function>                                                            */
1582*37da2899SCharles.Forsyth   /*    Decompose_Curve                                                    */
1583*37da2899SCharles.Forsyth   /*                                                                       */
1584*37da2899SCharles.Forsyth   /* <Description>                                                         */
1585*37da2899SCharles.Forsyth   /*    Scans the outline arays in order to emit individual segments and   */
1586*37da2899SCharles.Forsyth   /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
1587*37da2899SCharles.Forsyth   /*    weird cases, like when the first point is off the curve, or when   */
1588*37da2899SCharles.Forsyth   /*    there are simply no `on' points in the contour!                    */
1589*37da2899SCharles.Forsyth   /*                                                                       */
1590*37da2899SCharles.Forsyth   /* <Input>                                                               */
1591*37da2899SCharles.Forsyth   /*    first   :: The index of the first point in the contour.            */
1592*37da2899SCharles.Forsyth   /*                                                                       */
1593*37da2899SCharles.Forsyth   /*    last    :: The index of the last point in the contour.             */
1594*37da2899SCharles.Forsyth   /*                                                                       */
1595*37da2899SCharles.Forsyth   /*    flipped :: If set, flip the direction of the curve.                */
1596*37da2899SCharles.Forsyth   /*                                                                       */
1597*37da2899SCharles.Forsyth   /* <Return>                                                              */
1598*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE on error.                              */
1599*37da2899SCharles.Forsyth   /*                                                                       */
1600*37da2899SCharles.Forsyth   static Bool
Decompose_Curve(RAS_ARGS UShort first,UShort last,int flipped)1601*37da2899SCharles.Forsyth   Decompose_Curve( RAS_ARGS UShort  first,
1602*37da2899SCharles.Forsyth                             UShort  last,
1603*37da2899SCharles.Forsyth                             int     flipped )
1604*37da2899SCharles.Forsyth   {
1605*37da2899SCharles.Forsyth     FT_Vector   v_last;
1606*37da2899SCharles.Forsyth     FT_Vector   v_control;
1607*37da2899SCharles.Forsyth     FT_Vector   v_start;
1608*37da2899SCharles.Forsyth 
1609*37da2899SCharles.Forsyth     FT_Vector*  points;
1610*37da2899SCharles.Forsyth     FT_Vector*  point;
1611*37da2899SCharles.Forsyth     FT_Vector*  limit;
1612*37da2899SCharles.Forsyth     char*       tags;
1613*37da2899SCharles.Forsyth 
1614*37da2899SCharles.Forsyth     unsigned    tag;       /* current point's state           */
1615*37da2899SCharles.Forsyth 
1616*37da2899SCharles.Forsyth 
1617*37da2899SCharles.Forsyth     points = ras.outline.points;
1618*37da2899SCharles.Forsyth     limit  = points + last;
1619*37da2899SCharles.Forsyth 
1620*37da2899SCharles.Forsyth     v_start.x = SCALED( points[first].x );
1621*37da2899SCharles.Forsyth     v_start.y = SCALED( points[first].y );
1622*37da2899SCharles.Forsyth     v_last.x  = SCALED( points[last].x );
1623*37da2899SCharles.Forsyth     v_last.y  = SCALED( points[last].y );
1624*37da2899SCharles.Forsyth 
1625*37da2899SCharles.Forsyth     if ( flipped )
1626*37da2899SCharles.Forsyth     {
1627*37da2899SCharles.Forsyth       SWAP_( v_start.x, v_start.y );
1628*37da2899SCharles.Forsyth       SWAP_( v_last.x, v_last.y );
1629*37da2899SCharles.Forsyth     }
1630*37da2899SCharles.Forsyth 
1631*37da2899SCharles.Forsyth     v_control = v_start;
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth     point = points + first;
1634*37da2899SCharles.Forsyth     tags  = ras.outline.tags  + first;
1635*37da2899SCharles.Forsyth     tag   = FT_CURVE_TAG( tags[0] );
1636*37da2899SCharles.Forsyth 
1637*37da2899SCharles.Forsyth     /* A contour cannot start with a cubic control point! */
1638*37da2899SCharles.Forsyth     if ( tag == FT_CURVE_TAG_CUBIC )
1639*37da2899SCharles.Forsyth       goto Invalid_Outline;
1640*37da2899SCharles.Forsyth 
1641*37da2899SCharles.Forsyth     /* check first point to determine origin */
1642*37da2899SCharles.Forsyth     if ( tag == FT_CURVE_TAG_CONIC )
1643*37da2899SCharles.Forsyth     {
1644*37da2899SCharles.Forsyth       /* first point is conic control.  Yes, this happens. */
1645*37da2899SCharles.Forsyth       if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1646*37da2899SCharles.Forsyth       {
1647*37da2899SCharles.Forsyth         /* start at last point if it is on the curve */
1648*37da2899SCharles.Forsyth         v_start = v_last;
1649*37da2899SCharles.Forsyth         limit--;
1650*37da2899SCharles.Forsyth       }
1651*37da2899SCharles.Forsyth       else
1652*37da2899SCharles.Forsyth       {
1653*37da2899SCharles.Forsyth         /* if both first and last points are conic,         */
1654*37da2899SCharles.Forsyth         /* start at their middle and record its position    */
1655*37da2899SCharles.Forsyth         /* for closure                                      */
1656*37da2899SCharles.Forsyth         v_start.x = ( v_start.x + v_last.x ) / 2;
1657*37da2899SCharles.Forsyth         v_start.y = ( v_start.y + v_last.y ) / 2;
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth         v_last = v_start;
1660*37da2899SCharles.Forsyth       }
1661*37da2899SCharles.Forsyth       point--;
1662*37da2899SCharles.Forsyth       tags--;
1663*37da2899SCharles.Forsyth     }
1664*37da2899SCharles.Forsyth 
1665*37da2899SCharles.Forsyth     ras.lastX = v_start.x;
1666*37da2899SCharles.Forsyth     ras.lastY = v_start.y;
1667*37da2899SCharles.Forsyth 
1668*37da2899SCharles.Forsyth     while ( point < limit )
1669*37da2899SCharles.Forsyth     {
1670*37da2899SCharles.Forsyth       point++;
1671*37da2899SCharles.Forsyth       tags++;
1672*37da2899SCharles.Forsyth 
1673*37da2899SCharles.Forsyth       tag = FT_CURVE_TAG( tags[0] );
1674*37da2899SCharles.Forsyth 
1675*37da2899SCharles.Forsyth       switch ( tag )
1676*37da2899SCharles.Forsyth       {
1677*37da2899SCharles.Forsyth       case FT_CURVE_TAG_ON:  /* emit a single line_to */
1678*37da2899SCharles.Forsyth         {
1679*37da2899SCharles.Forsyth           Long  x, y;
1680*37da2899SCharles.Forsyth 
1681*37da2899SCharles.Forsyth 
1682*37da2899SCharles.Forsyth           x = SCALED( point->x );
1683*37da2899SCharles.Forsyth           y = SCALED( point->y );
1684*37da2899SCharles.Forsyth           if ( flipped )
1685*37da2899SCharles.Forsyth             SWAP_( x, y );
1686*37da2899SCharles.Forsyth 
1687*37da2899SCharles.Forsyth           if ( Line_To( RAS_VARS x, y ) )
1688*37da2899SCharles.Forsyth             goto Fail;
1689*37da2899SCharles.Forsyth           continue;
1690*37da2899SCharles.Forsyth         }
1691*37da2899SCharles.Forsyth 
1692*37da2899SCharles.Forsyth       case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
1693*37da2899SCharles.Forsyth         v_control.x = SCALED( point[0].x );
1694*37da2899SCharles.Forsyth         v_control.y = SCALED( point[0].y );
1695*37da2899SCharles.Forsyth 
1696*37da2899SCharles.Forsyth         if ( flipped )
1697*37da2899SCharles.Forsyth           SWAP_( v_control.x, v_control.y );
1698*37da2899SCharles.Forsyth 
1699*37da2899SCharles.Forsyth       Do_Conic:
1700*37da2899SCharles.Forsyth         if ( point < limit )
1701*37da2899SCharles.Forsyth         {
1702*37da2899SCharles.Forsyth           FT_Vector  v_middle;
1703*37da2899SCharles.Forsyth           Long       x, y;
1704*37da2899SCharles.Forsyth 
1705*37da2899SCharles.Forsyth 
1706*37da2899SCharles.Forsyth           point++;
1707*37da2899SCharles.Forsyth           tags++;
1708*37da2899SCharles.Forsyth           tag = FT_CURVE_TAG( tags[0] );
1709*37da2899SCharles.Forsyth 
1710*37da2899SCharles.Forsyth           x = SCALED( point[0].x );
1711*37da2899SCharles.Forsyth           y = SCALED( point[0].y );
1712*37da2899SCharles.Forsyth 
1713*37da2899SCharles.Forsyth           if ( flipped )
1714*37da2899SCharles.Forsyth             SWAP_( x, y );
1715*37da2899SCharles.Forsyth 
1716*37da2899SCharles.Forsyth           if ( tag == FT_CURVE_TAG_ON )
1717*37da2899SCharles.Forsyth           {
1718*37da2899SCharles.Forsyth             if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1719*37da2899SCharles.Forsyth               goto Fail;
1720*37da2899SCharles.Forsyth             continue;
1721*37da2899SCharles.Forsyth           }
1722*37da2899SCharles.Forsyth 
1723*37da2899SCharles.Forsyth           if ( tag != FT_CURVE_TAG_CONIC )
1724*37da2899SCharles.Forsyth             goto Invalid_Outline;
1725*37da2899SCharles.Forsyth 
1726*37da2899SCharles.Forsyth           v_middle.x = ( v_control.x + x ) / 2;
1727*37da2899SCharles.Forsyth           v_middle.y = ( v_control.y + y ) / 2;
1728*37da2899SCharles.Forsyth 
1729*37da2899SCharles.Forsyth           if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1730*37da2899SCharles.Forsyth                                   v_middle.x,  v_middle.y ) )
1731*37da2899SCharles.Forsyth             goto Fail;
1732*37da2899SCharles.Forsyth 
1733*37da2899SCharles.Forsyth           v_control.x = x;
1734*37da2899SCharles.Forsyth           v_control.y = y;
1735*37da2899SCharles.Forsyth 
1736*37da2899SCharles.Forsyth           goto Do_Conic;
1737*37da2899SCharles.Forsyth         }
1738*37da2899SCharles.Forsyth 
1739*37da2899SCharles.Forsyth         if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1740*37da2899SCharles.Forsyth                                 v_start.x,   v_start.y ) )
1741*37da2899SCharles.Forsyth           goto Fail;
1742*37da2899SCharles.Forsyth 
1743*37da2899SCharles.Forsyth         goto Close;
1744*37da2899SCharles.Forsyth 
1745*37da2899SCharles.Forsyth       default:  /* FT_CURVE_TAG_CUBIC */
1746*37da2899SCharles.Forsyth         {
1747*37da2899SCharles.Forsyth           Long  x1, y1, x2, y2, x3, y3;
1748*37da2899SCharles.Forsyth 
1749*37da2899SCharles.Forsyth 
1750*37da2899SCharles.Forsyth           if ( point + 1 > limit                             ||
1751*37da2899SCharles.Forsyth                FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1752*37da2899SCharles.Forsyth             goto Invalid_Outline;
1753*37da2899SCharles.Forsyth 
1754*37da2899SCharles.Forsyth           point += 2;
1755*37da2899SCharles.Forsyth           tags  += 2;
1756*37da2899SCharles.Forsyth 
1757*37da2899SCharles.Forsyth           x1 = SCALED( point[-2].x );
1758*37da2899SCharles.Forsyth           y1 = SCALED( point[-2].y );
1759*37da2899SCharles.Forsyth           x2 = SCALED( point[-1].x );
1760*37da2899SCharles.Forsyth           y2 = SCALED( point[-1].y );
1761*37da2899SCharles.Forsyth           x3 = SCALED( point[ 0].x );
1762*37da2899SCharles.Forsyth           y3 = SCALED( point[ 0].y );
1763*37da2899SCharles.Forsyth 
1764*37da2899SCharles.Forsyth           if ( flipped )
1765*37da2899SCharles.Forsyth           {
1766*37da2899SCharles.Forsyth             SWAP_( x1, y1 );
1767*37da2899SCharles.Forsyth             SWAP_( x2, y2 );
1768*37da2899SCharles.Forsyth             SWAP_( x3, y3 );
1769*37da2899SCharles.Forsyth           }
1770*37da2899SCharles.Forsyth 
1771*37da2899SCharles.Forsyth           if ( point <= limit )
1772*37da2899SCharles.Forsyth           {
1773*37da2899SCharles.Forsyth             if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1774*37da2899SCharles.Forsyth               goto Fail;
1775*37da2899SCharles.Forsyth             continue;
1776*37da2899SCharles.Forsyth           }
1777*37da2899SCharles.Forsyth 
1778*37da2899SCharles.Forsyth           if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1779*37da2899SCharles.Forsyth             goto Fail;
1780*37da2899SCharles.Forsyth           goto Close;
1781*37da2899SCharles.Forsyth         }
1782*37da2899SCharles.Forsyth       }
1783*37da2899SCharles.Forsyth     }
1784*37da2899SCharles.Forsyth 
1785*37da2899SCharles.Forsyth     /* close the contour with a line segment */
1786*37da2899SCharles.Forsyth     if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1787*37da2899SCharles.Forsyth       goto Fail;
1788*37da2899SCharles.Forsyth 
1789*37da2899SCharles.Forsyth   Close:
1790*37da2899SCharles.Forsyth     return SUCCESS;
1791*37da2899SCharles.Forsyth 
1792*37da2899SCharles.Forsyth   Invalid_Outline:
1793*37da2899SCharles.Forsyth     ras.error = Raster_Err_Invalid;
1794*37da2899SCharles.Forsyth 
1795*37da2899SCharles.Forsyth   Fail:
1796*37da2899SCharles.Forsyth     return FAILURE;
1797*37da2899SCharles.Forsyth   }
1798*37da2899SCharles.Forsyth 
1799*37da2899SCharles.Forsyth 
1800*37da2899SCharles.Forsyth   /*************************************************************************/
1801*37da2899SCharles.Forsyth   /*                                                                       */
1802*37da2899SCharles.Forsyth   /* <Function>                                                            */
1803*37da2899SCharles.Forsyth   /*    Convert_Glyph                                                      */
1804*37da2899SCharles.Forsyth   /*                                                                       */
1805*37da2899SCharles.Forsyth   /* <Description>                                                         */
1806*37da2899SCharles.Forsyth   /*    Converts a glyph into a series of segments and arcs and makes a    */
1807*37da2899SCharles.Forsyth   /*    profiles list with them.                                           */
1808*37da2899SCharles.Forsyth   /*                                                                       */
1809*37da2899SCharles.Forsyth   /* <Input>                                                               */
1810*37da2899SCharles.Forsyth   /*    flipped :: If set, flip the direction of curve.                    */
1811*37da2899SCharles.Forsyth   /*                                                                       */
1812*37da2899SCharles.Forsyth   /* <Return>                                                              */
1813*37da2899SCharles.Forsyth   /*    SUCCESS on success, FAILURE if any error was encountered during    */
1814*37da2899SCharles.Forsyth   /*    rendering.                                                         */
1815*37da2899SCharles.Forsyth   /*                                                                       */
1816*37da2899SCharles.Forsyth   static Bool
Convert_Glyph(RAS_ARGS int flipped)1817*37da2899SCharles.Forsyth   Convert_Glyph( RAS_ARGS int  flipped )
1818*37da2899SCharles.Forsyth   {
1819*37da2899SCharles.Forsyth     int       i;
1820*37da2899SCharles.Forsyth     unsigned  start;
1821*37da2899SCharles.Forsyth 
1822*37da2899SCharles.Forsyth     PProfile  lastProfile;
1823*37da2899SCharles.Forsyth 
1824*37da2899SCharles.Forsyth 
1825*37da2899SCharles.Forsyth     ras.fProfile = NULL;
1826*37da2899SCharles.Forsyth     ras.joint    = FALSE;
1827*37da2899SCharles.Forsyth     ras.fresh    = FALSE;
1828*37da2899SCharles.Forsyth 
1829*37da2899SCharles.Forsyth     ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
1830*37da2899SCharles.Forsyth 
1831*37da2899SCharles.Forsyth     ras.numTurns = 0;
1832*37da2899SCharles.Forsyth 
1833*37da2899SCharles.Forsyth     ras.cProfile         = (PProfile)ras.top;
1834*37da2899SCharles.Forsyth     ras.cProfile->offset = ras.top;
1835*37da2899SCharles.Forsyth     ras.num_Profs        = 0;
1836*37da2899SCharles.Forsyth 
1837*37da2899SCharles.Forsyth     start = 0;
1838*37da2899SCharles.Forsyth 
1839*37da2899SCharles.Forsyth     for ( i = 0; i < ras.outline.n_contours; i++ )
1840*37da2899SCharles.Forsyth     {
1841*37da2899SCharles.Forsyth       ras.state    = Unknown_State;
1842*37da2899SCharles.Forsyth       ras.gProfile = NULL;
1843*37da2899SCharles.Forsyth 
1844*37da2899SCharles.Forsyth       if ( Decompose_Curve( RAS_VARS (unsigned short)start,
1845*37da2899SCharles.Forsyth                             ras.outline.contours[i],
1846*37da2899SCharles.Forsyth                             flipped ) )
1847*37da2899SCharles.Forsyth         return FAILURE;
1848*37da2899SCharles.Forsyth 
1849*37da2899SCharles.Forsyth       start = ras.outline.contours[i] + 1;
1850*37da2899SCharles.Forsyth 
1851*37da2899SCharles.Forsyth       /* We must now see whether the extreme arcs join or not */
1852*37da2899SCharles.Forsyth       if ( FRAC( ras.lastY ) == 0 &&
1853*37da2899SCharles.Forsyth            ras.lastY >= ras.minY  &&
1854*37da2899SCharles.Forsyth            ras.lastY <= ras.maxY  )
1855*37da2899SCharles.Forsyth         if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
1856*37da2899SCharles.Forsyth           ras.top--;
1857*37da2899SCharles.Forsyth         /* Note that ras.gProfile can be nil if the contour was too small */
1858*37da2899SCharles.Forsyth         /* to be drawn.                                                   */
1859*37da2899SCharles.Forsyth 
1860*37da2899SCharles.Forsyth       lastProfile = ras.cProfile;
1861*37da2899SCharles.Forsyth       if ( End_Profile( RAS_VAR ) )
1862*37da2899SCharles.Forsyth         return FAILURE;
1863*37da2899SCharles.Forsyth 
1864*37da2899SCharles.Forsyth       /* close the `next profile in contour' linked list */
1865*37da2899SCharles.Forsyth       if ( ras.gProfile )
1866*37da2899SCharles.Forsyth         lastProfile->next = ras.gProfile;
1867*37da2899SCharles.Forsyth     }
1868*37da2899SCharles.Forsyth 
1869*37da2899SCharles.Forsyth     if ( Finalize_Profile_Table( RAS_VAR ) )
1870*37da2899SCharles.Forsyth       return FAILURE;
1871*37da2899SCharles.Forsyth 
1872*37da2899SCharles.Forsyth     return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
1873*37da2899SCharles.Forsyth   }
1874*37da2899SCharles.Forsyth 
1875*37da2899SCharles.Forsyth 
1876*37da2899SCharles.Forsyth   /*************************************************************************/
1877*37da2899SCharles.Forsyth   /*************************************************************************/
1878*37da2899SCharles.Forsyth   /**                                                                     **/
1879*37da2899SCharles.Forsyth   /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
1880*37da2899SCharles.Forsyth   /**                                                                     **/
1881*37da2899SCharles.Forsyth   /*************************************************************************/
1882*37da2899SCharles.Forsyth   /*************************************************************************/
1883*37da2899SCharles.Forsyth 
1884*37da2899SCharles.Forsyth 
1885*37da2899SCharles.Forsyth   /*************************************************************************/
1886*37da2899SCharles.Forsyth   /*                                                                       */
1887*37da2899SCharles.Forsyth   /*  Init_Linked                                                          */
1888*37da2899SCharles.Forsyth   /*                                                                       */
1889*37da2899SCharles.Forsyth   /*    Initializes an empty linked list.                                  */
1890*37da2899SCharles.Forsyth   /*                                                                       */
1891*37da2899SCharles.Forsyth   static void
Init_Linked(TProfileList * l)1892*37da2899SCharles.Forsyth   Init_Linked( TProfileList*  l )
1893*37da2899SCharles.Forsyth   {
1894*37da2899SCharles.Forsyth     *l = NULL;
1895*37da2899SCharles.Forsyth   }
1896*37da2899SCharles.Forsyth 
1897*37da2899SCharles.Forsyth 
1898*37da2899SCharles.Forsyth   /*************************************************************************/
1899*37da2899SCharles.Forsyth   /*                                                                       */
1900*37da2899SCharles.Forsyth   /*  InsNew                                                               */
1901*37da2899SCharles.Forsyth   /*                                                                       */
1902*37da2899SCharles.Forsyth   /*    Inserts a new profile in a linked list.                            */
1903*37da2899SCharles.Forsyth   /*                                                                       */
1904*37da2899SCharles.Forsyth   static void
InsNew(PProfileList list,PProfile profile)1905*37da2899SCharles.Forsyth   InsNew( PProfileList  list,
1906*37da2899SCharles.Forsyth           PProfile      profile )
1907*37da2899SCharles.Forsyth   {
1908*37da2899SCharles.Forsyth     PProfile  *old, current;
1909*37da2899SCharles.Forsyth     Long       x;
1910*37da2899SCharles.Forsyth 
1911*37da2899SCharles.Forsyth 
1912*37da2899SCharles.Forsyth     old     = list;
1913*37da2899SCharles.Forsyth     current = *old;
1914*37da2899SCharles.Forsyth     x       = profile->X;
1915*37da2899SCharles.Forsyth 
1916*37da2899SCharles.Forsyth     while ( current )
1917*37da2899SCharles.Forsyth     {
1918*37da2899SCharles.Forsyth       if ( x < current->X )
1919*37da2899SCharles.Forsyth         break;
1920*37da2899SCharles.Forsyth       old     = &current->link;
1921*37da2899SCharles.Forsyth       current = *old;
1922*37da2899SCharles.Forsyth     }
1923*37da2899SCharles.Forsyth 
1924*37da2899SCharles.Forsyth     profile->link = current;
1925*37da2899SCharles.Forsyth     *old          = profile;
1926*37da2899SCharles.Forsyth   }
1927*37da2899SCharles.Forsyth 
1928*37da2899SCharles.Forsyth 
1929*37da2899SCharles.Forsyth   /*************************************************************************/
1930*37da2899SCharles.Forsyth   /*                                                                       */
1931*37da2899SCharles.Forsyth   /*  DelOld                                                               */
1932*37da2899SCharles.Forsyth   /*                                                                       */
1933*37da2899SCharles.Forsyth   /*    Removes an old profile from a linked list.                         */
1934*37da2899SCharles.Forsyth   /*                                                                       */
1935*37da2899SCharles.Forsyth   static void
DelOld(PProfileList list,PProfile profile)1936*37da2899SCharles.Forsyth   DelOld( PProfileList  list,
1937*37da2899SCharles.Forsyth           PProfile      profile )
1938*37da2899SCharles.Forsyth   {
1939*37da2899SCharles.Forsyth     PProfile  *old, current;
1940*37da2899SCharles.Forsyth 
1941*37da2899SCharles.Forsyth 
1942*37da2899SCharles.Forsyth     old     = list;
1943*37da2899SCharles.Forsyth     current = *old;
1944*37da2899SCharles.Forsyth 
1945*37da2899SCharles.Forsyth     while ( current )
1946*37da2899SCharles.Forsyth     {
1947*37da2899SCharles.Forsyth       if ( current == profile )
1948*37da2899SCharles.Forsyth       {
1949*37da2899SCharles.Forsyth         *old = current->link;
1950*37da2899SCharles.Forsyth         return;
1951*37da2899SCharles.Forsyth       }
1952*37da2899SCharles.Forsyth 
1953*37da2899SCharles.Forsyth       old     = &current->link;
1954*37da2899SCharles.Forsyth       current = *old;
1955*37da2899SCharles.Forsyth     }
1956*37da2899SCharles.Forsyth 
1957*37da2899SCharles.Forsyth     /* we should never get there, unless the profile was not part of */
1958*37da2899SCharles.Forsyth     /* the list.                                                     */
1959*37da2899SCharles.Forsyth   }
1960*37da2899SCharles.Forsyth 
1961*37da2899SCharles.Forsyth 
1962*37da2899SCharles.Forsyth   /*************************************************************************/
1963*37da2899SCharles.Forsyth   /*                                                                       */
1964*37da2899SCharles.Forsyth   /*  Sort                                                                 */
1965*37da2899SCharles.Forsyth   /*                                                                       */
1966*37da2899SCharles.Forsyth   /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
1967*37da2899SCharles.Forsyth   /*    an algorithm which is fast in this case.  Bubble sort is enough    */
1968*37da2899SCharles.Forsyth   /*    and simple.                                                        */
1969*37da2899SCharles.Forsyth   /*                                                                       */
1970*37da2899SCharles.Forsyth   static void
Sort(PProfileList list)1971*37da2899SCharles.Forsyth   Sort( PProfileList  list )
1972*37da2899SCharles.Forsyth   {
1973*37da2899SCharles.Forsyth     PProfile  *old, current, next;
1974*37da2899SCharles.Forsyth 
1975*37da2899SCharles.Forsyth 
1976*37da2899SCharles.Forsyth     /* First, set the new X coordinate of each profile */
1977*37da2899SCharles.Forsyth     current = *list;
1978*37da2899SCharles.Forsyth     while ( current )
1979*37da2899SCharles.Forsyth     {
1980*37da2899SCharles.Forsyth       current->X       = *current->offset;
1981*37da2899SCharles.Forsyth       current->offset += current->flow;
1982*37da2899SCharles.Forsyth       current->height--;
1983*37da2899SCharles.Forsyth       current = current->link;
1984*37da2899SCharles.Forsyth     }
1985*37da2899SCharles.Forsyth 
1986*37da2899SCharles.Forsyth     /* Then sort them */
1987*37da2899SCharles.Forsyth     old     = list;
1988*37da2899SCharles.Forsyth     current = *old;
1989*37da2899SCharles.Forsyth 
1990*37da2899SCharles.Forsyth     if ( !current )
1991*37da2899SCharles.Forsyth       return;
1992*37da2899SCharles.Forsyth 
1993*37da2899SCharles.Forsyth     next = current->link;
1994*37da2899SCharles.Forsyth 
1995*37da2899SCharles.Forsyth     while ( next )
1996*37da2899SCharles.Forsyth     {
1997*37da2899SCharles.Forsyth       if ( current->X <= next->X )
1998*37da2899SCharles.Forsyth       {
1999*37da2899SCharles.Forsyth         old     = &current->link;
2000*37da2899SCharles.Forsyth         current = *old;
2001*37da2899SCharles.Forsyth 
2002*37da2899SCharles.Forsyth         if ( !current )
2003*37da2899SCharles.Forsyth           return;
2004*37da2899SCharles.Forsyth       }
2005*37da2899SCharles.Forsyth       else
2006*37da2899SCharles.Forsyth       {
2007*37da2899SCharles.Forsyth         *old          = next;
2008*37da2899SCharles.Forsyth         current->link = next->link;
2009*37da2899SCharles.Forsyth         next->link    = current;
2010*37da2899SCharles.Forsyth 
2011*37da2899SCharles.Forsyth         old     = list;
2012*37da2899SCharles.Forsyth         current = *old;
2013*37da2899SCharles.Forsyth       }
2014*37da2899SCharles.Forsyth 
2015*37da2899SCharles.Forsyth       next = current->link;
2016*37da2899SCharles.Forsyth     }
2017*37da2899SCharles.Forsyth   }
2018*37da2899SCharles.Forsyth 
2019*37da2899SCharles.Forsyth 
2020*37da2899SCharles.Forsyth   /*************************************************************************/
2021*37da2899SCharles.Forsyth   /*                                                                       */
2022*37da2899SCharles.Forsyth   /*  Vertical Sweep Procedure Set                                         */
2023*37da2899SCharles.Forsyth   /*                                                                       */
2024*37da2899SCharles.Forsyth   /*  These four routines are used during the vertical black/white sweep   */
2025*37da2899SCharles.Forsyth   /*  phase by the generic Draw_Sweep() function.                          */
2026*37da2899SCharles.Forsyth   /*                                                                       */
2027*37da2899SCharles.Forsyth   /*************************************************************************/
2028*37da2899SCharles.Forsyth 
2029*37da2899SCharles.Forsyth   static void
Vertical_Sweep_Init(RAS_ARGS Short * min,Short * max)2030*37da2899SCharles.Forsyth   Vertical_Sweep_Init( RAS_ARGS Short*  min,
2031*37da2899SCharles.Forsyth                                 Short*  max )
2032*37da2899SCharles.Forsyth   {
2033*37da2899SCharles.Forsyth     Long  pitch = ras.target.pitch;
2034*37da2899SCharles.Forsyth 
2035*37da2899SCharles.Forsyth     FT_UNUSED( max );
2036*37da2899SCharles.Forsyth 
2037*37da2899SCharles.Forsyth 
2038*37da2899SCharles.Forsyth     ras.traceIncr = (Short)-pitch;
2039*37da2899SCharles.Forsyth     ras.traceOfs  = -*min * pitch;
2040*37da2899SCharles.Forsyth     if ( pitch > 0 )
2041*37da2899SCharles.Forsyth       ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
2042*37da2899SCharles.Forsyth 
2043*37da2899SCharles.Forsyth     ras.gray_min_x = 0;
2044*37da2899SCharles.Forsyth     ras.gray_max_x = 0;
2045*37da2899SCharles.Forsyth   }
2046*37da2899SCharles.Forsyth 
2047*37da2899SCharles.Forsyth 
2048*37da2899SCharles.Forsyth   static void
Vertical_Sweep_Span(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2049*37da2899SCharles.Forsyth   Vertical_Sweep_Span( RAS_ARGS Short       y,
2050*37da2899SCharles.Forsyth                                 FT_F26Dot6  x1,
2051*37da2899SCharles.Forsyth                                 FT_F26Dot6  x2,
2052*37da2899SCharles.Forsyth                                 PProfile    left,
2053*37da2899SCharles.Forsyth                                 PProfile    right )
2054*37da2899SCharles.Forsyth   {
2055*37da2899SCharles.Forsyth     Long   e1, e2;
2056*37da2899SCharles.Forsyth     int    c1, c2;
2057*37da2899SCharles.Forsyth     Byte   f1, f2;
2058*37da2899SCharles.Forsyth     Byte*  target;
2059*37da2899SCharles.Forsyth 
2060*37da2899SCharles.Forsyth     FT_UNUSED( y );
2061*37da2899SCharles.Forsyth     FT_UNUSED( left );
2062*37da2899SCharles.Forsyth     FT_UNUSED( right );
2063*37da2899SCharles.Forsyth 
2064*37da2899SCharles.Forsyth 
2065*37da2899SCharles.Forsyth     /* Drop-out control */
2066*37da2899SCharles.Forsyth 
2067*37da2899SCharles.Forsyth     e1 = TRUNC( CEILING( x1 ) );
2068*37da2899SCharles.Forsyth 
2069*37da2899SCharles.Forsyth     if ( x2 - x1 - ras.precision <= ras.precision_jitter )
2070*37da2899SCharles.Forsyth       e2 = e1;
2071*37da2899SCharles.Forsyth     else
2072*37da2899SCharles.Forsyth       e2 = TRUNC( FLOOR( x2 ) );
2073*37da2899SCharles.Forsyth 
2074*37da2899SCharles.Forsyth     if ( e2 >= 0 && e1 < ras.bWidth )
2075*37da2899SCharles.Forsyth     {
2076*37da2899SCharles.Forsyth       if ( e1 < 0 )
2077*37da2899SCharles.Forsyth         e1 = 0;
2078*37da2899SCharles.Forsyth       if ( e2 >= ras.bWidth )
2079*37da2899SCharles.Forsyth         e2 = ras.bWidth - 1;
2080*37da2899SCharles.Forsyth 
2081*37da2899SCharles.Forsyth       c1 = (Short)( e1 >> 3 );
2082*37da2899SCharles.Forsyth       c2 = (Short)( e2 >> 3 );
2083*37da2899SCharles.Forsyth 
2084*37da2899SCharles.Forsyth       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
2085*37da2899SCharles.Forsyth       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2086*37da2899SCharles.Forsyth 
2087*37da2899SCharles.Forsyth       if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
2088*37da2899SCharles.Forsyth       if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
2089*37da2899SCharles.Forsyth 
2090*37da2899SCharles.Forsyth       target = ras.bTarget + ras.traceOfs + c1;
2091*37da2899SCharles.Forsyth       c2 -= c1;
2092*37da2899SCharles.Forsyth 
2093*37da2899SCharles.Forsyth       if ( c2 > 0 )
2094*37da2899SCharles.Forsyth       {
2095*37da2899SCharles.Forsyth         target[0] |= f1;
2096*37da2899SCharles.Forsyth 
2097*37da2899SCharles.Forsyth         /* memset() is slower than the following code on many platforms. */
2098*37da2899SCharles.Forsyth         /* This is due to the fact that, in the vast majority of cases,  */
2099*37da2899SCharles.Forsyth         /* the span length in bytes is relatively small.                 */
2100*37da2899SCharles.Forsyth         c2--;
2101*37da2899SCharles.Forsyth         while ( c2 > 0 )
2102*37da2899SCharles.Forsyth         {
2103*37da2899SCharles.Forsyth           *(++target) = 0xFF;
2104*37da2899SCharles.Forsyth           c2--;
2105*37da2899SCharles.Forsyth         }
2106*37da2899SCharles.Forsyth         target[1] |= f2;
2107*37da2899SCharles.Forsyth       }
2108*37da2899SCharles.Forsyth       else
2109*37da2899SCharles.Forsyth         *target |= ( f1 & f2 );
2110*37da2899SCharles.Forsyth     }
2111*37da2899SCharles.Forsyth   }
2112*37da2899SCharles.Forsyth 
2113*37da2899SCharles.Forsyth 
2114*37da2899SCharles.Forsyth   static void
Vertical_Sweep_Drop(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2115*37da2899SCharles.Forsyth   Vertical_Sweep_Drop( RAS_ARGS Short       y,
2116*37da2899SCharles.Forsyth                                 FT_F26Dot6  x1,
2117*37da2899SCharles.Forsyth                                 FT_F26Dot6  x2,
2118*37da2899SCharles.Forsyth                                 PProfile    left,
2119*37da2899SCharles.Forsyth                                 PProfile    right )
2120*37da2899SCharles.Forsyth   {
2121*37da2899SCharles.Forsyth     Long   e1, e2;
2122*37da2899SCharles.Forsyth     Short  c1, f1;
2123*37da2899SCharles.Forsyth 
2124*37da2899SCharles.Forsyth 
2125*37da2899SCharles.Forsyth     /* Drop-out control */
2126*37da2899SCharles.Forsyth 
2127*37da2899SCharles.Forsyth     e1 = CEILING( x1 );
2128*37da2899SCharles.Forsyth     e2 = FLOOR  ( x2 );
2129*37da2899SCharles.Forsyth 
2130*37da2899SCharles.Forsyth     if ( e1 > e2 )
2131*37da2899SCharles.Forsyth     {
2132*37da2899SCharles.Forsyth       if ( e1 == e2 + ras.precision )
2133*37da2899SCharles.Forsyth       {
2134*37da2899SCharles.Forsyth         switch ( ras.dropOutControl )
2135*37da2899SCharles.Forsyth         {
2136*37da2899SCharles.Forsyth         case 1:
2137*37da2899SCharles.Forsyth           e1 = e2;
2138*37da2899SCharles.Forsyth           break;
2139*37da2899SCharles.Forsyth 
2140*37da2899SCharles.Forsyth         case 4:
2141*37da2899SCharles.Forsyth           e1 = CEILING( (x1 + x2 + 1) / 2 );
2142*37da2899SCharles.Forsyth           break;
2143*37da2899SCharles.Forsyth 
2144*37da2899SCharles.Forsyth         case 2:
2145*37da2899SCharles.Forsyth         case 5:
2146*37da2899SCharles.Forsyth           /* Drop-out Control Rule #4 */
2147*37da2899SCharles.Forsyth 
2148*37da2899SCharles.Forsyth           /* The spec is not very clear regarding rule #4.  It      */
2149*37da2899SCharles.Forsyth           /* presents a method that is way too costly to implement  */
2150*37da2899SCharles.Forsyth           /* while the general idea seems to get rid of `stubs'.    */
2151*37da2899SCharles.Forsyth           /*                                                        */
2152*37da2899SCharles.Forsyth           /* Here, we only get rid of stubs recognized if:          */
2153*37da2899SCharles.Forsyth           /*                                                        */
2154*37da2899SCharles.Forsyth           /*  upper stub:                                           */
2155*37da2899SCharles.Forsyth           /*                                                        */
2156*37da2899SCharles.Forsyth           /*   - P_Left and P_Right are in the same contour         */
2157*37da2899SCharles.Forsyth           /*   - P_Right is the successor of P_Left in that contour */
2158*37da2899SCharles.Forsyth           /*   - y is the top of P_Left and P_Right                 */
2159*37da2899SCharles.Forsyth           /*                                                        */
2160*37da2899SCharles.Forsyth           /*  lower stub:                                           */
2161*37da2899SCharles.Forsyth           /*                                                        */
2162*37da2899SCharles.Forsyth           /*   - P_Left and P_Right are in the same contour         */
2163*37da2899SCharles.Forsyth           /*   - P_Left is the successor of P_Right in that contour */
2164*37da2899SCharles.Forsyth           /*   - y is the bottom of P_Left                          */
2165*37da2899SCharles.Forsyth           /*                                                        */
2166*37da2899SCharles.Forsyth 
2167*37da2899SCharles.Forsyth           /* FIXXXME: uncommenting this line solves the disappearing */
2168*37da2899SCharles.Forsyth           /*          bit problem in the `7' of verdana 10pts, but   */
2169*37da2899SCharles.Forsyth           /*          makes a new one in the `C' of arial 14pts      */
2170*37da2899SCharles.Forsyth 
2171*37da2899SCharles.Forsyth #if 0
2172*37da2899SCharles.Forsyth           if ( x2 - x1 < ras.precision_half )
2173*37da2899SCharles.Forsyth #endif
2174*37da2899SCharles.Forsyth           {
2175*37da2899SCharles.Forsyth             /* upper stub test */
2176*37da2899SCharles.Forsyth             if ( left->next == right && left->height <= 0 )
2177*37da2899SCharles.Forsyth               return;
2178*37da2899SCharles.Forsyth 
2179*37da2899SCharles.Forsyth             /* lower stub test */
2180*37da2899SCharles.Forsyth             if ( right->next == left && left->start == y )
2181*37da2899SCharles.Forsyth               return;
2182*37da2899SCharles.Forsyth           }
2183*37da2899SCharles.Forsyth 
2184*37da2899SCharles.Forsyth           /* check that the rightmost pixel isn't set */
2185*37da2899SCharles.Forsyth 
2186*37da2899SCharles.Forsyth           e1 = TRUNC( e1 );
2187*37da2899SCharles.Forsyth 
2188*37da2899SCharles.Forsyth           c1 = (Short)( e1 >> 3 );
2189*37da2899SCharles.Forsyth           f1 = (Short)( e1 &  7 );
2190*37da2899SCharles.Forsyth 
2191*37da2899SCharles.Forsyth           if ( e1 >= 0 && e1 < ras.bWidth                      &&
2192*37da2899SCharles.Forsyth                ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
2193*37da2899SCharles.Forsyth             return;
2194*37da2899SCharles.Forsyth 
2195*37da2899SCharles.Forsyth           if ( ras.dropOutControl == 2 )
2196*37da2899SCharles.Forsyth             e1 = e2;
2197*37da2899SCharles.Forsyth           else
2198*37da2899SCharles.Forsyth             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
2199*37da2899SCharles.Forsyth 
2200*37da2899SCharles.Forsyth           break;
2201*37da2899SCharles.Forsyth 
2202*37da2899SCharles.Forsyth         default:
2203*37da2899SCharles.Forsyth           return;  /* unsupported mode */
2204*37da2899SCharles.Forsyth         }
2205*37da2899SCharles.Forsyth       }
2206*37da2899SCharles.Forsyth       else
2207*37da2899SCharles.Forsyth         return;
2208*37da2899SCharles.Forsyth     }
2209*37da2899SCharles.Forsyth 
2210*37da2899SCharles.Forsyth     e1 = TRUNC( e1 );
2211*37da2899SCharles.Forsyth 
2212*37da2899SCharles.Forsyth     if ( e1 >= 0 && e1 < ras.bWidth )
2213*37da2899SCharles.Forsyth     {
2214*37da2899SCharles.Forsyth       c1 = (Short)( e1 >> 3 );
2215*37da2899SCharles.Forsyth       f1 = (Short)( e1 & 7 );
2216*37da2899SCharles.Forsyth 
2217*37da2899SCharles.Forsyth       if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
2218*37da2899SCharles.Forsyth       if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
2219*37da2899SCharles.Forsyth 
2220*37da2899SCharles.Forsyth       ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2221*37da2899SCharles.Forsyth     }
2222*37da2899SCharles.Forsyth   }
2223*37da2899SCharles.Forsyth 
2224*37da2899SCharles.Forsyth 
2225*37da2899SCharles.Forsyth   static void
Vertical_Sweep_Step(RAS_ARG)2226*37da2899SCharles.Forsyth   Vertical_Sweep_Step( RAS_ARG )
2227*37da2899SCharles.Forsyth   {
2228*37da2899SCharles.Forsyth     ras.traceOfs += ras.traceIncr;
2229*37da2899SCharles.Forsyth   }
2230*37da2899SCharles.Forsyth 
2231*37da2899SCharles.Forsyth 
2232*37da2899SCharles.Forsyth   /***********************************************************************/
2233*37da2899SCharles.Forsyth   /*                                                                     */
2234*37da2899SCharles.Forsyth   /*  Horizontal Sweep Procedure Set                                     */
2235*37da2899SCharles.Forsyth   /*                                                                     */
2236*37da2899SCharles.Forsyth   /*  These four routines are used during the horizontal black/white     */
2237*37da2899SCharles.Forsyth   /*  sweep phase by the generic Draw_Sweep() function.                  */
2238*37da2899SCharles.Forsyth   /*                                                                     */
2239*37da2899SCharles.Forsyth   /***********************************************************************/
2240*37da2899SCharles.Forsyth 
2241*37da2899SCharles.Forsyth   static void
Horizontal_Sweep_Init(RAS_ARGS Short * min,Short * max)2242*37da2899SCharles.Forsyth   Horizontal_Sweep_Init( RAS_ARGS Short*  min,
2243*37da2899SCharles.Forsyth                                   Short*  max )
2244*37da2899SCharles.Forsyth   {
2245*37da2899SCharles.Forsyth     /* nothing, really */
2246*37da2899SCharles.Forsyth     FT_UNUSED( raster );
2247*37da2899SCharles.Forsyth     FT_UNUSED( min );
2248*37da2899SCharles.Forsyth     FT_UNUSED( max );
2249*37da2899SCharles.Forsyth   }
2250*37da2899SCharles.Forsyth 
2251*37da2899SCharles.Forsyth 
2252*37da2899SCharles.Forsyth   static void
Horizontal_Sweep_Span(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2253*37da2899SCharles.Forsyth   Horizontal_Sweep_Span( RAS_ARGS Short       y,
2254*37da2899SCharles.Forsyth                                   FT_F26Dot6  x1,
2255*37da2899SCharles.Forsyth                                   FT_F26Dot6  x2,
2256*37da2899SCharles.Forsyth                                   PProfile    left,
2257*37da2899SCharles.Forsyth                                   PProfile    right )
2258*37da2899SCharles.Forsyth   {
2259*37da2899SCharles.Forsyth     Long   e1, e2;
2260*37da2899SCharles.Forsyth     PByte  bits;
2261*37da2899SCharles.Forsyth     Byte   f1;
2262*37da2899SCharles.Forsyth 
2263*37da2899SCharles.Forsyth     FT_UNUSED( left );
2264*37da2899SCharles.Forsyth     FT_UNUSED( right );
2265*37da2899SCharles.Forsyth 
2266*37da2899SCharles.Forsyth 
2267*37da2899SCharles.Forsyth     if ( x2 - x1 < ras.precision )
2268*37da2899SCharles.Forsyth     {
2269*37da2899SCharles.Forsyth       e1 = CEILING( x1 );
2270*37da2899SCharles.Forsyth       e2 = FLOOR  ( x2 );
2271*37da2899SCharles.Forsyth 
2272*37da2899SCharles.Forsyth       if ( e1 == e2 )
2273*37da2899SCharles.Forsyth       {
2274*37da2899SCharles.Forsyth         bits = ras.bTarget + ( y >> 3 );
2275*37da2899SCharles.Forsyth         f1   = (Byte)( 0x80 >> ( y & 7 ) );
2276*37da2899SCharles.Forsyth 
2277*37da2899SCharles.Forsyth         e1 = TRUNC( e1 );
2278*37da2899SCharles.Forsyth 
2279*37da2899SCharles.Forsyth         if ( e1 >= 0 && e1 < ras.target.rows )
2280*37da2899SCharles.Forsyth         {
2281*37da2899SCharles.Forsyth           PByte  p;
2282*37da2899SCharles.Forsyth 
2283*37da2899SCharles.Forsyth 
2284*37da2899SCharles.Forsyth           p = bits - e1*ras.target.pitch;
2285*37da2899SCharles.Forsyth           if ( ras.target.pitch > 0 )
2286*37da2899SCharles.Forsyth             p += ( ras.target.rows - 1 ) * ras.target.pitch;
2287*37da2899SCharles.Forsyth 
2288*37da2899SCharles.Forsyth           p[0] |= f1;
2289*37da2899SCharles.Forsyth         }
2290*37da2899SCharles.Forsyth       }
2291*37da2899SCharles.Forsyth     }
2292*37da2899SCharles.Forsyth   }
2293*37da2899SCharles.Forsyth 
2294*37da2899SCharles.Forsyth 
2295*37da2899SCharles.Forsyth   static void
Horizontal_Sweep_Drop(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2296*37da2899SCharles.Forsyth   Horizontal_Sweep_Drop( RAS_ARGS Short       y,
2297*37da2899SCharles.Forsyth                                   FT_F26Dot6  x1,
2298*37da2899SCharles.Forsyth                                   FT_F26Dot6  x2,
2299*37da2899SCharles.Forsyth                                   PProfile    left,
2300*37da2899SCharles.Forsyth                                   PProfile    right )
2301*37da2899SCharles.Forsyth   {
2302*37da2899SCharles.Forsyth     Long   e1, e2;
2303*37da2899SCharles.Forsyth     PByte  bits;
2304*37da2899SCharles.Forsyth     Byte   f1;
2305*37da2899SCharles.Forsyth 
2306*37da2899SCharles.Forsyth 
2307*37da2899SCharles.Forsyth     /* During the horizontal sweep, we only take care of drop-outs */
2308*37da2899SCharles.Forsyth 
2309*37da2899SCharles.Forsyth     e1 = CEILING( x1 );
2310*37da2899SCharles.Forsyth     e2 = FLOOR  ( x2 );
2311*37da2899SCharles.Forsyth 
2312*37da2899SCharles.Forsyth     if ( e1 > e2 )
2313*37da2899SCharles.Forsyth     {
2314*37da2899SCharles.Forsyth       if ( e1 == e2 + ras.precision )
2315*37da2899SCharles.Forsyth       {
2316*37da2899SCharles.Forsyth         switch ( ras.dropOutControl )
2317*37da2899SCharles.Forsyth         {
2318*37da2899SCharles.Forsyth         case 1:
2319*37da2899SCharles.Forsyth           e1 = e2;
2320*37da2899SCharles.Forsyth           break;
2321*37da2899SCharles.Forsyth 
2322*37da2899SCharles.Forsyth         case 4:
2323*37da2899SCharles.Forsyth           e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
2324*37da2899SCharles.Forsyth           break;
2325*37da2899SCharles.Forsyth 
2326*37da2899SCharles.Forsyth         case 2:
2327*37da2899SCharles.Forsyth         case 5:
2328*37da2899SCharles.Forsyth 
2329*37da2899SCharles.Forsyth           /* Drop-out Control Rule #4 */
2330*37da2899SCharles.Forsyth 
2331*37da2899SCharles.Forsyth           /* The spec is not very clear regarding rule #4.  It      */
2332*37da2899SCharles.Forsyth           /* presents a method that is way too costly to implement  */
2333*37da2899SCharles.Forsyth           /* while the general idea seems to get rid of `stubs'.    */
2334*37da2899SCharles.Forsyth           /*                                                        */
2335*37da2899SCharles.Forsyth 
2336*37da2899SCharles.Forsyth           /* rightmost stub test */
2337*37da2899SCharles.Forsyth           if ( left->next == right && left->height <= 0 )
2338*37da2899SCharles.Forsyth             return;
2339*37da2899SCharles.Forsyth 
2340*37da2899SCharles.Forsyth           /* leftmost stub test */
2341*37da2899SCharles.Forsyth           if ( right->next == left && left->start == y )
2342*37da2899SCharles.Forsyth             return;
2343*37da2899SCharles.Forsyth 
2344*37da2899SCharles.Forsyth           /* check that the rightmost pixel isn't set */
2345*37da2899SCharles.Forsyth 
2346*37da2899SCharles.Forsyth           e1 = TRUNC( e1 );
2347*37da2899SCharles.Forsyth 
2348*37da2899SCharles.Forsyth           bits = ras.bTarget + ( y >> 3 );
2349*37da2899SCharles.Forsyth           f1   = (Byte)( 0x80 >> ( y & 7 ) );
2350*37da2899SCharles.Forsyth 
2351*37da2899SCharles.Forsyth           bits -= e1 * ras.target.pitch;
2352*37da2899SCharles.Forsyth           if ( ras.target.pitch > 0 )
2353*37da2899SCharles.Forsyth             bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2354*37da2899SCharles.Forsyth 
2355*37da2899SCharles.Forsyth           if ( e1 >= 0              &&
2356*37da2899SCharles.Forsyth                e1 < ras.target.rows &&
2357*37da2899SCharles.Forsyth                *bits & f1 )
2358*37da2899SCharles.Forsyth             return;
2359*37da2899SCharles.Forsyth 
2360*37da2899SCharles.Forsyth           if ( ras.dropOutControl == 2 )
2361*37da2899SCharles.Forsyth             e1 = e2;
2362*37da2899SCharles.Forsyth           else
2363*37da2899SCharles.Forsyth             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
2364*37da2899SCharles.Forsyth 
2365*37da2899SCharles.Forsyth           break;
2366*37da2899SCharles.Forsyth 
2367*37da2899SCharles.Forsyth         default:
2368*37da2899SCharles.Forsyth           return;  /* unsupported mode */
2369*37da2899SCharles.Forsyth         }
2370*37da2899SCharles.Forsyth       }
2371*37da2899SCharles.Forsyth       else
2372*37da2899SCharles.Forsyth         return;
2373*37da2899SCharles.Forsyth     }
2374*37da2899SCharles.Forsyth 
2375*37da2899SCharles.Forsyth     bits = ras.bTarget + ( y >> 3 );
2376*37da2899SCharles.Forsyth     f1   = (Byte)( 0x80 >> ( y & 7 ) );
2377*37da2899SCharles.Forsyth 
2378*37da2899SCharles.Forsyth     e1 = TRUNC( e1 );
2379*37da2899SCharles.Forsyth 
2380*37da2899SCharles.Forsyth     if ( e1 >= 0 && e1 < ras.target.rows )
2381*37da2899SCharles.Forsyth     {
2382*37da2899SCharles.Forsyth       bits -= e1 * ras.target.pitch;
2383*37da2899SCharles.Forsyth       if ( ras.target.pitch > 0 )
2384*37da2899SCharles.Forsyth         bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2385*37da2899SCharles.Forsyth 
2386*37da2899SCharles.Forsyth       bits[0] |= f1;
2387*37da2899SCharles.Forsyth     }
2388*37da2899SCharles.Forsyth   }
2389*37da2899SCharles.Forsyth 
2390*37da2899SCharles.Forsyth 
2391*37da2899SCharles.Forsyth   static void
Horizontal_Sweep_Step(RAS_ARG)2392*37da2899SCharles.Forsyth   Horizontal_Sweep_Step( RAS_ARG )
2393*37da2899SCharles.Forsyth   {
2394*37da2899SCharles.Forsyth     /* Nothing, really */
2395*37da2899SCharles.Forsyth     FT_UNUSED( raster );
2396*37da2899SCharles.Forsyth   }
2397*37da2899SCharles.Forsyth 
2398*37da2899SCharles.Forsyth 
2399*37da2899SCharles.Forsyth #ifdef FT_RASTER_OPTION_ANTI_ALIASING
2400*37da2899SCharles.Forsyth 
2401*37da2899SCharles.Forsyth 
2402*37da2899SCharles.Forsyth   /*************************************************************************/
2403*37da2899SCharles.Forsyth   /*                                                                       */
2404*37da2899SCharles.Forsyth   /*  Vertical Gray Sweep Procedure Set                                    */
2405*37da2899SCharles.Forsyth   /*                                                                       */
2406*37da2899SCharles.Forsyth   /*  These two routines are used during the vertical gray-levels sweep    */
2407*37da2899SCharles.Forsyth   /*  phase by the generic Draw_Sweep() function.                          */
2408*37da2899SCharles.Forsyth   /*                                                                       */
2409*37da2899SCharles.Forsyth   /*  NOTES                                                                */
2410*37da2899SCharles.Forsyth   /*                                                                       */
2411*37da2899SCharles.Forsyth   /*  - The target pixmap's width *must* be a multiple of 4.               */
2412*37da2899SCharles.Forsyth   /*                                                                       */
2413*37da2899SCharles.Forsyth   /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
2414*37da2899SCharles.Forsyth   /*    span call.                                                         */
2415*37da2899SCharles.Forsyth   /*                                                                       */
2416*37da2899SCharles.Forsyth   /*************************************************************************/
2417*37da2899SCharles.Forsyth 
2418*37da2899SCharles.Forsyth   static void
Vertical_Gray_Sweep_Init(RAS_ARGS Short * min,Short * max)2419*37da2899SCharles.Forsyth   Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
2420*37da2899SCharles.Forsyth                                      Short*  max )
2421*37da2899SCharles.Forsyth   {
2422*37da2899SCharles.Forsyth     Long  pitch, byte_len;
2423*37da2899SCharles.Forsyth 
2424*37da2899SCharles.Forsyth 
2425*37da2899SCharles.Forsyth     *min = *min & -2;
2426*37da2899SCharles.Forsyth     *max = ( *max + 3 ) & -2;
2427*37da2899SCharles.Forsyth 
2428*37da2899SCharles.Forsyth     ras.traceOfs  = 0;
2429*37da2899SCharles.Forsyth     pitch         = ras.target.pitch;
2430*37da2899SCharles.Forsyth     byte_len      = -pitch;
2431*37da2899SCharles.Forsyth     ras.traceIncr = (Short)byte_len;
2432*37da2899SCharles.Forsyth     ras.traceG    = ( *min / 2 ) * byte_len;
2433*37da2899SCharles.Forsyth 
2434*37da2899SCharles.Forsyth     if ( pitch > 0 )
2435*37da2899SCharles.Forsyth     {
2436*37da2899SCharles.Forsyth       ras.traceG += ( ras.target.rows - 1 ) * pitch;
2437*37da2899SCharles.Forsyth       byte_len    = -byte_len;
2438*37da2899SCharles.Forsyth     }
2439*37da2899SCharles.Forsyth 
2440*37da2899SCharles.Forsyth     ras.gray_min_x =  (Short)byte_len;
2441*37da2899SCharles.Forsyth     ras.gray_max_x = -(Short)byte_len;
2442*37da2899SCharles.Forsyth   }
2443*37da2899SCharles.Forsyth 
2444*37da2899SCharles.Forsyth 
2445*37da2899SCharles.Forsyth   static void
Vertical_Gray_Sweep_Step(RAS_ARG)2446*37da2899SCharles.Forsyth   Vertical_Gray_Sweep_Step( RAS_ARG )
2447*37da2899SCharles.Forsyth   {
2448*37da2899SCharles.Forsyth     Int    c1, c2;
2449*37da2899SCharles.Forsyth     PByte  pix, bit, bit2;
2450*37da2899SCharles.Forsyth     Int*   count = ras.count_table;
2451*37da2899SCharles.Forsyth     Byte*  grays;
2452*37da2899SCharles.Forsyth 
2453*37da2899SCharles.Forsyth 
2454*37da2899SCharles.Forsyth     ras.traceOfs += ras.gray_width;
2455*37da2899SCharles.Forsyth 
2456*37da2899SCharles.Forsyth     if ( ras.traceOfs > ras.gray_width )
2457*37da2899SCharles.Forsyth     {
2458*37da2899SCharles.Forsyth       pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
2459*37da2899SCharles.Forsyth       grays = ras.grays;
2460*37da2899SCharles.Forsyth 
2461*37da2899SCharles.Forsyth       if ( ras.gray_max_x >= 0 )
2462*37da2899SCharles.Forsyth       {
2463*37da2899SCharles.Forsyth         Long   last_pixel = ras.target.width - 1;
2464*37da2899SCharles.Forsyth         Int    last_cell  = last_pixel >> 2;
2465*37da2899SCharles.Forsyth         Int    last_bit   = last_pixel & 3;
2466*37da2899SCharles.Forsyth         Bool   over       = 0;
2467*37da2899SCharles.Forsyth 
2468*37da2899SCharles.Forsyth 
2469*37da2899SCharles.Forsyth         if ( ras.gray_max_x >= last_cell && last_bit != 3 )
2470*37da2899SCharles.Forsyth         {
2471*37da2899SCharles.Forsyth           ras.gray_max_x = last_cell - 1;
2472*37da2899SCharles.Forsyth           over = 1;
2473*37da2899SCharles.Forsyth         }
2474*37da2899SCharles.Forsyth 
2475*37da2899SCharles.Forsyth         if ( ras.gray_min_x < 0 )
2476*37da2899SCharles.Forsyth           ras.gray_min_x = 0;
2477*37da2899SCharles.Forsyth 
2478*37da2899SCharles.Forsyth         bit   = ras.bTarget + ras.gray_min_x;
2479*37da2899SCharles.Forsyth         bit2  = bit + ras.gray_width;
2480*37da2899SCharles.Forsyth 
2481*37da2899SCharles.Forsyth         c1 = ras.gray_max_x - ras.gray_min_x;
2482*37da2899SCharles.Forsyth 
2483*37da2899SCharles.Forsyth         while ( c1 >= 0 )
2484*37da2899SCharles.Forsyth         {
2485*37da2899SCharles.Forsyth           c2 = count[*bit] + count[*bit2];
2486*37da2899SCharles.Forsyth 
2487*37da2899SCharles.Forsyth           if ( c2 )
2488*37da2899SCharles.Forsyth           {
2489*37da2899SCharles.Forsyth             pix[0] = grays[(c2 >> 12) & 0x000F];
2490*37da2899SCharles.Forsyth             pix[1] = grays[(c2 >> 8 ) & 0x000F];
2491*37da2899SCharles.Forsyth             pix[2] = grays[(c2 >> 4 ) & 0x000F];
2492*37da2899SCharles.Forsyth             pix[3] = grays[ c2        & 0x000F];
2493*37da2899SCharles.Forsyth 
2494*37da2899SCharles.Forsyth             *bit  = 0;
2495*37da2899SCharles.Forsyth             *bit2 = 0;
2496*37da2899SCharles.Forsyth           }
2497*37da2899SCharles.Forsyth 
2498*37da2899SCharles.Forsyth           bit++;
2499*37da2899SCharles.Forsyth           bit2++;
2500*37da2899SCharles.Forsyth           pix += 4;
2501*37da2899SCharles.Forsyth           c1--;
2502*37da2899SCharles.Forsyth         }
2503*37da2899SCharles.Forsyth 
2504*37da2899SCharles.Forsyth         if ( over )
2505*37da2899SCharles.Forsyth         {
2506*37da2899SCharles.Forsyth           c2 = count[*bit] + count[*bit2];
2507*37da2899SCharles.Forsyth           if ( c2 )
2508*37da2899SCharles.Forsyth           {
2509*37da2899SCharles.Forsyth             switch ( last_bit )
2510*37da2899SCharles.Forsyth             {
2511*37da2899SCharles.Forsyth             case 2:
2512*37da2899SCharles.Forsyth               pix[2] = grays[(c2 >> 4 ) & 0x000F];
2513*37da2899SCharles.Forsyth             case 1:
2514*37da2899SCharles.Forsyth               pix[1] = grays[(c2 >> 8 ) & 0x000F];
2515*37da2899SCharles.Forsyth             default:
2516*37da2899SCharles.Forsyth               pix[0] = grays[(c2 >> 12) & 0x000F];
2517*37da2899SCharles.Forsyth             }
2518*37da2899SCharles.Forsyth 
2519*37da2899SCharles.Forsyth             *bit  = 0;
2520*37da2899SCharles.Forsyth             *bit2 = 0;
2521*37da2899SCharles.Forsyth           }
2522*37da2899SCharles.Forsyth         }
2523*37da2899SCharles.Forsyth       }
2524*37da2899SCharles.Forsyth 
2525*37da2899SCharles.Forsyth       ras.traceOfs = 0;
2526*37da2899SCharles.Forsyth       ras.traceG  += ras.traceIncr;
2527*37da2899SCharles.Forsyth 
2528*37da2899SCharles.Forsyth       ras.gray_min_x =  32000;
2529*37da2899SCharles.Forsyth       ras.gray_max_x = -32000;
2530*37da2899SCharles.Forsyth     }
2531*37da2899SCharles.Forsyth   }
2532*37da2899SCharles.Forsyth 
2533*37da2899SCharles.Forsyth 
2534*37da2899SCharles.Forsyth   static void
Horizontal_Gray_Sweep_Span(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2535*37da2899SCharles.Forsyth   Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
2536*37da2899SCharles.Forsyth                                        FT_F26Dot6  x1,
2537*37da2899SCharles.Forsyth                                        FT_F26Dot6  x2,
2538*37da2899SCharles.Forsyth                                        PProfile    left,
2539*37da2899SCharles.Forsyth                                        PProfile    right )
2540*37da2899SCharles.Forsyth   {
2541*37da2899SCharles.Forsyth     /* nothing, really */
2542*37da2899SCharles.Forsyth     FT_UNUSED( raster );
2543*37da2899SCharles.Forsyth     FT_UNUSED( y );
2544*37da2899SCharles.Forsyth     FT_UNUSED( x1 );
2545*37da2899SCharles.Forsyth     FT_UNUSED( x2 );
2546*37da2899SCharles.Forsyth     FT_UNUSED( left );
2547*37da2899SCharles.Forsyth     FT_UNUSED( right );
2548*37da2899SCharles.Forsyth   }
2549*37da2899SCharles.Forsyth 
2550*37da2899SCharles.Forsyth 
2551*37da2899SCharles.Forsyth   static void
Horizontal_Gray_Sweep_Drop(RAS_ARGS Short y,FT_F26Dot6 x1,FT_F26Dot6 x2,PProfile left,PProfile right)2552*37da2899SCharles.Forsyth   Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
2553*37da2899SCharles.Forsyth                                        FT_F26Dot6  x1,
2554*37da2899SCharles.Forsyth                                        FT_F26Dot6  x2,
2555*37da2899SCharles.Forsyth                                        PProfile    left,
2556*37da2899SCharles.Forsyth                                        PProfile    right )
2557*37da2899SCharles.Forsyth   {
2558*37da2899SCharles.Forsyth     Long   e1, e2;
2559*37da2899SCharles.Forsyth     PByte  pixel;
2560*37da2899SCharles.Forsyth     Byte   color;
2561*37da2899SCharles.Forsyth 
2562*37da2899SCharles.Forsyth 
2563*37da2899SCharles.Forsyth     /* During the horizontal sweep, we only take care of drop-outs */
2564*37da2899SCharles.Forsyth     e1 = CEILING( x1 );
2565*37da2899SCharles.Forsyth     e2 = FLOOR  ( x2 );
2566*37da2899SCharles.Forsyth 
2567*37da2899SCharles.Forsyth     if ( e1 > e2 )
2568*37da2899SCharles.Forsyth     {
2569*37da2899SCharles.Forsyth       if ( e1 == e2 + ras.precision )
2570*37da2899SCharles.Forsyth       {
2571*37da2899SCharles.Forsyth         switch ( ras.dropOutControl )
2572*37da2899SCharles.Forsyth         {
2573*37da2899SCharles.Forsyth         case 1:
2574*37da2899SCharles.Forsyth           e1 = e2;
2575*37da2899SCharles.Forsyth           break;
2576*37da2899SCharles.Forsyth 
2577*37da2899SCharles.Forsyth         case 4:
2578*37da2899SCharles.Forsyth           e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
2579*37da2899SCharles.Forsyth           break;
2580*37da2899SCharles.Forsyth 
2581*37da2899SCharles.Forsyth         case 2:
2582*37da2899SCharles.Forsyth         case 5:
2583*37da2899SCharles.Forsyth 
2584*37da2899SCharles.Forsyth           /* Drop-out Control Rule #4 */
2585*37da2899SCharles.Forsyth 
2586*37da2899SCharles.Forsyth           /* The spec is not very clear regarding rule #4.  It      */
2587*37da2899SCharles.Forsyth           /* presents a method that is way too costly to implement  */
2588*37da2899SCharles.Forsyth           /* while the general idea seems to get rid of `stubs'.    */
2589*37da2899SCharles.Forsyth           /*                                                        */
2590*37da2899SCharles.Forsyth 
2591*37da2899SCharles.Forsyth           /* rightmost stub test */
2592*37da2899SCharles.Forsyth           if ( left->next == right && left->height <= 0 )
2593*37da2899SCharles.Forsyth             return;
2594*37da2899SCharles.Forsyth 
2595*37da2899SCharles.Forsyth           /* leftmost stub test */
2596*37da2899SCharles.Forsyth           if ( right->next == left && left->start == y )
2597*37da2899SCharles.Forsyth             return;
2598*37da2899SCharles.Forsyth 
2599*37da2899SCharles.Forsyth           if ( ras.dropOutControl == 2 )
2600*37da2899SCharles.Forsyth             e1 = e2;
2601*37da2899SCharles.Forsyth           else
2602*37da2899SCharles.Forsyth             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
2603*37da2899SCharles.Forsyth 
2604*37da2899SCharles.Forsyth           break;
2605*37da2899SCharles.Forsyth 
2606*37da2899SCharles.Forsyth         default:
2607*37da2899SCharles.Forsyth           return;  /* unsupported mode */
2608*37da2899SCharles.Forsyth         }
2609*37da2899SCharles.Forsyth       }
2610*37da2899SCharles.Forsyth       else
2611*37da2899SCharles.Forsyth         return;
2612*37da2899SCharles.Forsyth     }
2613*37da2899SCharles.Forsyth 
2614*37da2899SCharles.Forsyth     if ( e1 >= 0 )
2615*37da2899SCharles.Forsyth     {
2616*37da2899SCharles.Forsyth       if ( x2 - x1 >= ras.precision_half )
2617*37da2899SCharles.Forsyth         color = ras.grays[2];
2618*37da2899SCharles.Forsyth       else
2619*37da2899SCharles.Forsyth         color = ras.grays[1];
2620*37da2899SCharles.Forsyth 
2621*37da2899SCharles.Forsyth       e1 = TRUNC( e1 ) / 2;
2622*37da2899SCharles.Forsyth       if ( e1 < ras.target.rows )
2623*37da2899SCharles.Forsyth       {
2624*37da2899SCharles.Forsyth         pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
2625*37da2899SCharles.Forsyth         if ( ras.target.pitch > 0 )
2626*37da2899SCharles.Forsyth           pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
2627*37da2899SCharles.Forsyth 
2628*37da2899SCharles.Forsyth         if ( pixel[0] == ras.grays[0] )
2629*37da2899SCharles.Forsyth           pixel[0] = color;
2630*37da2899SCharles.Forsyth       }
2631*37da2899SCharles.Forsyth     }
2632*37da2899SCharles.Forsyth   }
2633*37da2899SCharles.Forsyth 
2634*37da2899SCharles.Forsyth 
2635*37da2899SCharles.Forsyth #endif /* FT_RASTER_OPTION_ANTI_ALIASING */
2636*37da2899SCharles.Forsyth 
2637*37da2899SCharles.Forsyth 
2638*37da2899SCharles.Forsyth   /*************************************************************************/
2639*37da2899SCharles.Forsyth   /*                                                                       */
2640*37da2899SCharles.Forsyth   /*  Generic Sweep Drawing routine                                        */
2641*37da2899SCharles.Forsyth   /*                                                                       */
2642*37da2899SCharles.Forsyth   /*************************************************************************/
2643*37da2899SCharles.Forsyth 
2644*37da2899SCharles.Forsyth   static Bool
Draw_Sweep(RAS_ARG)2645*37da2899SCharles.Forsyth   Draw_Sweep( RAS_ARG )
2646*37da2899SCharles.Forsyth   {
2647*37da2899SCharles.Forsyth     Short         y, y_change, y_height;
2648*37da2899SCharles.Forsyth 
2649*37da2899SCharles.Forsyth     PProfile      P, Q, P_Left, P_Right;
2650*37da2899SCharles.Forsyth 
2651*37da2899SCharles.Forsyth     Short         min_Y, max_Y, top, bottom, dropouts;
2652*37da2899SCharles.Forsyth 
2653*37da2899SCharles.Forsyth     Long          x1, x2, xs, e1, e2;
2654*37da2899SCharles.Forsyth 
2655*37da2899SCharles.Forsyth     TProfileList  waiting;
2656*37da2899SCharles.Forsyth     TProfileList  draw_left, draw_right;
2657*37da2899SCharles.Forsyth 
2658*37da2899SCharles.Forsyth 
2659*37da2899SCharles.Forsyth     /* Init empty linked lists */
2660*37da2899SCharles.Forsyth 
2661*37da2899SCharles.Forsyth     Init_Linked( &waiting );
2662*37da2899SCharles.Forsyth 
2663*37da2899SCharles.Forsyth     Init_Linked( &draw_left  );
2664*37da2899SCharles.Forsyth     Init_Linked( &draw_right );
2665*37da2899SCharles.Forsyth 
2666*37da2899SCharles.Forsyth     /* first, compute min and max Y */
2667*37da2899SCharles.Forsyth 
2668*37da2899SCharles.Forsyth     P     = ras.fProfile;
2669*37da2899SCharles.Forsyth     max_Y = (Short)TRUNC( ras.minY );
2670*37da2899SCharles.Forsyth     min_Y = (Short)TRUNC( ras.maxY );
2671*37da2899SCharles.Forsyth 
2672*37da2899SCharles.Forsyth     while ( P )
2673*37da2899SCharles.Forsyth     {
2674*37da2899SCharles.Forsyth       Q = P->link;
2675*37da2899SCharles.Forsyth 
2676*37da2899SCharles.Forsyth       bottom = (Short)P->start;
2677*37da2899SCharles.Forsyth       top    = (Short)( P->start + P->height - 1 );
2678*37da2899SCharles.Forsyth 
2679*37da2899SCharles.Forsyth       if ( min_Y > bottom ) min_Y = bottom;
2680*37da2899SCharles.Forsyth       if ( max_Y < top    ) max_Y = top;
2681*37da2899SCharles.Forsyth 
2682*37da2899SCharles.Forsyth       P->X = 0;
2683*37da2899SCharles.Forsyth       InsNew( &waiting, P );
2684*37da2899SCharles.Forsyth 
2685*37da2899SCharles.Forsyth       P = Q;
2686*37da2899SCharles.Forsyth     }
2687*37da2899SCharles.Forsyth 
2688*37da2899SCharles.Forsyth     /* Check the Y-turns */
2689*37da2899SCharles.Forsyth     if ( ras.numTurns == 0 )
2690*37da2899SCharles.Forsyth     {
2691*37da2899SCharles.Forsyth       ras.error = Raster_Err_Invalid;
2692*37da2899SCharles.Forsyth       return FAILURE;
2693*37da2899SCharles.Forsyth     }
2694*37da2899SCharles.Forsyth 
2695*37da2899SCharles.Forsyth     /* Now inits the sweep */
2696*37da2899SCharles.Forsyth 
2697*37da2899SCharles.Forsyth     ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2698*37da2899SCharles.Forsyth 
2699*37da2899SCharles.Forsyth     /* Then compute the distance of each profile from min_Y */
2700*37da2899SCharles.Forsyth 
2701*37da2899SCharles.Forsyth     P = waiting;
2702*37da2899SCharles.Forsyth 
2703*37da2899SCharles.Forsyth     while ( P )
2704*37da2899SCharles.Forsyth     {
2705*37da2899SCharles.Forsyth       P->countL = (UShort)( P->start - min_Y );
2706*37da2899SCharles.Forsyth       P = P->link;
2707*37da2899SCharles.Forsyth     }
2708*37da2899SCharles.Forsyth 
2709*37da2899SCharles.Forsyth     /* Let's go */
2710*37da2899SCharles.Forsyth 
2711*37da2899SCharles.Forsyth     y        = min_Y;
2712*37da2899SCharles.Forsyth     y_height = 0;
2713*37da2899SCharles.Forsyth 
2714*37da2899SCharles.Forsyth     if ( ras.numTurns > 0 &&
2715*37da2899SCharles.Forsyth          ras.sizeBuff[-ras.numTurns] == min_Y )
2716*37da2899SCharles.Forsyth       ras.numTurns--;
2717*37da2899SCharles.Forsyth 
2718*37da2899SCharles.Forsyth     while ( ras.numTurns > 0 )
2719*37da2899SCharles.Forsyth     {
2720*37da2899SCharles.Forsyth       /* look in the waiting list for new activations */
2721*37da2899SCharles.Forsyth 
2722*37da2899SCharles.Forsyth       P = waiting;
2723*37da2899SCharles.Forsyth 
2724*37da2899SCharles.Forsyth       while ( P )
2725*37da2899SCharles.Forsyth       {
2726*37da2899SCharles.Forsyth         Q = P->link;
2727*37da2899SCharles.Forsyth         P->countL -= y_height;
2728*37da2899SCharles.Forsyth         if ( P->countL == 0 )
2729*37da2899SCharles.Forsyth         {
2730*37da2899SCharles.Forsyth           DelOld( &waiting, P );
2731*37da2899SCharles.Forsyth 
2732*37da2899SCharles.Forsyth           switch ( P->flow )
2733*37da2899SCharles.Forsyth           {
2734*37da2899SCharles.Forsyth           case Flow_Up:
2735*37da2899SCharles.Forsyth             InsNew( &draw_left,  P );
2736*37da2899SCharles.Forsyth             break;
2737*37da2899SCharles.Forsyth 
2738*37da2899SCharles.Forsyth           case Flow_Down:
2739*37da2899SCharles.Forsyth             InsNew( &draw_right, P );
2740*37da2899SCharles.Forsyth             break;
2741*37da2899SCharles.Forsyth           }
2742*37da2899SCharles.Forsyth         }
2743*37da2899SCharles.Forsyth 
2744*37da2899SCharles.Forsyth         P = Q;
2745*37da2899SCharles.Forsyth       }
2746*37da2899SCharles.Forsyth 
2747*37da2899SCharles.Forsyth       /* Sort the drawing lists */
2748*37da2899SCharles.Forsyth 
2749*37da2899SCharles.Forsyth       Sort( &draw_left );
2750*37da2899SCharles.Forsyth       Sort( &draw_right );
2751*37da2899SCharles.Forsyth 
2752*37da2899SCharles.Forsyth       y_change = (Short)ras.sizeBuff[-ras.numTurns--];
2753*37da2899SCharles.Forsyth       y_height = (Short)( y_change - y );
2754*37da2899SCharles.Forsyth 
2755*37da2899SCharles.Forsyth       while ( y < y_change )
2756*37da2899SCharles.Forsyth       {
2757*37da2899SCharles.Forsyth         /* Let's trace */
2758*37da2899SCharles.Forsyth 
2759*37da2899SCharles.Forsyth         dropouts = 0;
2760*37da2899SCharles.Forsyth 
2761*37da2899SCharles.Forsyth         P_Left  = draw_left;
2762*37da2899SCharles.Forsyth         P_Right = draw_right;
2763*37da2899SCharles.Forsyth 
2764*37da2899SCharles.Forsyth         while ( P_Left )
2765*37da2899SCharles.Forsyth         {
2766*37da2899SCharles.Forsyth           x1 = P_Left ->X;
2767*37da2899SCharles.Forsyth           x2 = P_Right->X;
2768*37da2899SCharles.Forsyth 
2769*37da2899SCharles.Forsyth           if ( x1 > x2 )
2770*37da2899SCharles.Forsyth           {
2771*37da2899SCharles.Forsyth             xs = x1;
2772*37da2899SCharles.Forsyth             x1 = x2;
2773*37da2899SCharles.Forsyth             x2 = xs;
2774*37da2899SCharles.Forsyth           }
2775*37da2899SCharles.Forsyth 
2776*37da2899SCharles.Forsyth           if ( x2 - x1 <= ras.precision )
2777*37da2899SCharles.Forsyth           {
2778*37da2899SCharles.Forsyth             e1 = FLOOR( x1 );
2779*37da2899SCharles.Forsyth             e2 = CEILING( x2 );
2780*37da2899SCharles.Forsyth 
2781*37da2899SCharles.Forsyth             if ( ras.dropOutControl != 0                 &&
2782*37da2899SCharles.Forsyth                  ( e1 > e2 || e2 == e1 + ras.precision ) )
2783*37da2899SCharles.Forsyth             {
2784*37da2899SCharles.Forsyth               /* a drop out was detected */
2785*37da2899SCharles.Forsyth 
2786*37da2899SCharles.Forsyth               P_Left ->X = x1;
2787*37da2899SCharles.Forsyth               P_Right->X = x2;
2788*37da2899SCharles.Forsyth 
2789*37da2899SCharles.Forsyth               /* mark profile for drop-out processing */
2790*37da2899SCharles.Forsyth               P_Left->countL = 1;
2791*37da2899SCharles.Forsyth               dropouts++;
2792*37da2899SCharles.Forsyth 
2793*37da2899SCharles.Forsyth               goto Skip_To_Next;
2794*37da2899SCharles.Forsyth             }
2795*37da2899SCharles.Forsyth           }
2796*37da2899SCharles.Forsyth 
2797*37da2899SCharles.Forsyth           ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
2798*37da2899SCharles.Forsyth 
2799*37da2899SCharles.Forsyth         Skip_To_Next:
2800*37da2899SCharles.Forsyth 
2801*37da2899SCharles.Forsyth           P_Left  = P_Left->link;
2802*37da2899SCharles.Forsyth           P_Right = P_Right->link;
2803*37da2899SCharles.Forsyth         }
2804*37da2899SCharles.Forsyth 
2805*37da2899SCharles.Forsyth         /* now perform the dropouts _after_ the span drawing -- */
2806*37da2899SCharles.Forsyth         /* drop-outs processing has been moved out of the loop  */
2807*37da2899SCharles.Forsyth         /* for performance tuning                               */
2808*37da2899SCharles.Forsyth         if ( dropouts > 0 )
2809*37da2899SCharles.Forsyth           goto Scan_DropOuts;
2810*37da2899SCharles.Forsyth 
2811*37da2899SCharles.Forsyth       Next_Line:
2812*37da2899SCharles.Forsyth 
2813*37da2899SCharles.Forsyth         ras.Proc_Sweep_Step( RAS_VAR );
2814*37da2899SCharles.Forsyth 
2815*37da2899SCharles.Forsyth         y++;
2816*37da2899SCharles.Forsyth 
2817*37da2899SCharles.Forsyth         if ( y < y_change )
2818*37da2899SCharles.Forsyth         {
2819*37da2899SCharles.Forsyth           Sort( &draw_left  );
2820*37da2899SCharles.Forsyth           Sort( &draw_right );
2821*37da2899SCharles.Forsyth         }
2822*37da2899SCharles.Forsyth       }
2823*37da2899SCharles.Forsyth 
2824*37da2899SCharles.Forsyth       /* Now finalize the profiles that needs it */
2825*37da2899SCharles.Forsyth 
2826*37da2899SCharles.Forsyth       P = draw_left;
2827*37da2899SCharles.Forsyth       while ( P )
2828*37da2899SCharles.Forsyth       {
2829*37da2899SCharles.Forsyth         Q = P->link;
2830*37da2899SCharles.Forsyth         if ( P->height == 0 )
2831*37da2899SCharles.Forsyth           DelOld( &draw_left, P );
2832*37da2899SCharles.Forsyth         P = Q;
2833*37da2899SCharles.Forsyth       }
2834*37da2899SCharles.Forsyth 
2835*37da2899SCharles.Forsyth       P = draw_right;
2836*37da2899SCharles.Forsyth       while ( P )
2837*37da2899SCharles.Forsyth       {
2838*37da2899SCharles.Forsyth         Q = P->link;
2839*37da2899SCharles.Forsyth         if ( P->height == 0 )
2840*37da2899SCharles.Forsyth           DelOld( &draw_right, P );
2841*37da2899SCharles.Forsyth         P = Q;
2842*37da2899SCharles.Forsyth       }
2843*37da2899SCharles.Forsyth     }
2844*37da2899SCharles.Forsyth 
2845*37da2899SCharles.Forsyth     /* for gray-scaling, flushes the bitmap scanline cache */
2846*37da2899SCharles.Forsyth     while ( y <= max_Y )
2847*37da2899SCharles.Forsyth     {
2848*37da2899SCharles.Forsyth       ras.Proc_Sweep_Step( RAS_VAR );
2849*37da2899SCharles.Forsyth       y++;
2850*37da2899SCharles.Forsyth     }
2851*37da2899SCharles.Forsyth 
2852*37da2899SCharles.Forsyth     return SUCCESS;
2853*37da2899SCharles.Forsyth 
2854*37da2899SCharles.Forsyth   Scan_DropOuts:
2855*37da2899SCharles.Forsyth 
2856*37da2899SCharles.Forsyth     P_Left  = draw_left;
2857*37da2899SCharles.Forsyth     P_Right = draw_right;
2858*37da2899SCharles.Forsyth 
2859*37da2899SCharles.Forsyth     while ( P_Left )
2860*37da2899SCharles.Forsyth     {
2861*37da2899SCharles.Forsyth       if ( P_Left->countL )
2862*37da2899SCharles.Forsyth       {
2863*37da2899SCharles.Forsyth         P_Left->countL = 0;
2864*37da2899SCharles.Forsyth #if 0
2865*37da2899SCharles.Forsyth         dropouts--;  /* -- this is useful when debugging only */
2866*37da2899SCharles.Forsyth #endif
2867*37da2899SCharles.Forsyth         ras.Proc_Sweep_Drop( RAS_VARS y,
2868*37da2899SCharles.Forsyth                                       P_Left->X,
2869*37da2899SCharles.Forsyth                                       P_Right->X,
2870*37da2899SCharles.Forsyth                                       P_Left,
2871*37da2899SCharles.Forsyth                                       P_Right );
2872*37da2899SCharles.Forsyth       }
2873*37da2899SCharles.Forsyth 
2874*37da2899SCharles.Forsyth       P_Left  = P_Left->link;
2875*37da2899SCharles.Forsyth       P_Right = P_Right->link;
2876*37da2899SCharles.Forsyth     }
2877*37da2899SCharles.Forsyth 
2878*37da2899SCharles.Forsyth     goto Next_Line;
2879*37da2899SCharles.Forsyth   }
2880*37da2899SCharles.Forsyth 
2881*37da2899SCharles.Forsyth 
2882*37da2899SCharles.Forsyth   /*************************************************************************/
2883*37da2899SCharles.Forsyth   /*                                                                       */
2884*37da2899SCharles.Forsyth   /* <Function>                                                            */
2885*37da2899SCharles.Forsyth   /*    Render_Single_Pass                                                 */
2886*37da2899SCharles.Forsyth   /*                                                                       */
2887*37da2899SCharles.Forsyth   /* <Description>                                                         */
2888*37da2899SCharles.Forsyth   /*    Performs one sweep with sub-banding.                               */
2889*37da2899SCharles.Forsyth   /*                                                                       */
2890*37da2899SCharles.Forsyth   /* <Input>                                                               */
2891*37da2899SCharles.Forsyth   /*    flipped :: If set, flip the direction of the outline.              */
2892*37da2899SCharles.Forsyth   /*                                                                       */
2893*37da2899SCharles.Forsyth   /* <Return>                                                              */
2894*37da2899SCharles.Forsyth   /*    Renderer error code.                                               */
2895*37da2899SCharles.Forsyth   /*                                                                       */
2896*37da2899SCharles.Forsyth   static int
Render_Single_Pass(RAS_ARGS Bool flipped)2897*37da2899SCharles.Forsyth   Render_Single_Pass( RAS_ARGS Bool  flipped )
2898*37da2899SCharles.Forsyth   {
2899*37da2899SCharles.Forsyth     Short  i, j, k;
2900*37da2899SCharles.Forsyth 
2901*37da2899SCharles.Forsyth 
2902*37da2899SCharles.Forsyth     while ( ras.band_top >= 0 )
2903*37da2899SCharles.Forsyth     {
2904*37da2899SCharles.Forsyth       ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
2905*37da2899SCharles.Forsyth       ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
2906*37da2899SCharles.Forsyth 
2907*37da2899SCharles.Forsyth       ras.top = ras.buff;
2908*37da2899SCharles.Forsyth 
2909*37da2899SCharles.Forsyth       ras.error = Raster_Err_None;
2910*37da2899SCharles.Forsyth 
2911*37da2899SCharles.Forsyth       if ( Convert_Glyph( RAS_VARS flipped ) )
2912*37da2899SCharles.Forsyth       {
2913*37da2899SCharles.Forsyth         if ( ras.error != Raster_Err_Overflow )
2914*37da2899SCharles.Forsyth           return FAILURE;
2915*37da2899SCharles.Forsyth 
2916*37da2899SCharles.Forsyth         ras.error = Raster_Err_None;
2917*37da2899SCharles.Forsyth 
2918*37da2899SCharles.Forsyth         /* sub-banding */
2919*37da2899SCharles.Forsyth 
2920*37da2899SCharles.Forsyth #ifdef DEBUG_RASTER
2921*37da2899SCharles.Forsyth         ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
2922*37da2899SCharles.Forsyth #endif
2923*37da2899SCharles.Forsyth 
2924*37da2899SCharles.Forsyth         i = ras.band_stack[ras.band_top].y_min;
2925*37da2899SCharles.Forsyth         j = ras.band_stack[ras.band_top].y_max;
2926*37da2899SCharles.Forsyth 
2927*37da2899SCharles.Forsyth         k = (Short)( ( i + j ) / 2 );
2928*37da2899SCharles.Forsyth 
2929*37da2899SCharles.Forsyth         if ( ras.band_top >= 7 || k < i )
2930*37da2899SCharles.Forsyth         {
2931*37da2899SCharles.Forsyth           ras.band_top = 0;
2932*37da2899SCharles.Forsyth           ras.error    = Raster_Err_Invalid;
2933*37da2899SCharles.Forsyth 
2934*37da2899SCharles.Forsyth           return ras.error;
2935*37da2899SCharles.Forsyth         }
2936*37da2899SCharles.Forsyth 
2937*37da2899SCharles.Forsyth         ras.band_stack[ras.band_top + 1].y_min = k;
2938*37da2899SCharles.Forsyth         ras.band_stack[ras.band_top + 1].y_max = j;
2939*37da2899SCharles.Forsyth 
2940*37da2899SCharles.Forsyth         ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
2941*37da2899SCharles.Forsyth 
2942*37da2899SCharles.Forsyth         ras.band_top++;
2943*37da2899SCharles.Forsyth       }
2944*37da2899SCharles.Forsyth       else
2945*37da2899SCharles.Forsyth       {
2946*37da2899SCharles.Forsyth         if ( ras.fProfile )
2947*37da2899SCharles.Forsyth           if ( Draw_Sweep( RAS_VAR ) )
2948*37da2899SCharles.Forsyth              return ras.error;
2949*37da2899SCharles.Forsyth         ras.band_top--;
2950*37da2899SCharles.Forsyth       }
2951*37da2899SCharles.Forsyth     }
2952*37da2899SCharles.Forsyth 
2953*37da2899SCharles.Forsyth     return SUCCESS;
2954*37da2899SCharles.Forsyth   }
2955*37da2899SCharles.Forsyth 
2956*37da2899SCharles.Forsyth 
2957*37da2899SCharles.Forsyth   /*************************************************************************/
2958*37da2899SCharles.Forsyth   /*                                                                       */
2959*37da2899SCharles.Forsyth   /* <Function>                                                            */
2960*37da2899SCharles.Forsyth   /*    Render_Glyph                                                       */
2961*37da2899SCharles.Forsyth   /*                                                                       */
2962*37da2899SCharles.Forsyth   /* <Description>                                                         */
2963*37da2899SCharles.Forsyth   /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
2964*37da2899SCharles.Forsyth   /*                                                                       */
2965*37da2899SCharles.Forsyth   /* <Return>                                                              */
2966*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
2967*37da2899SCharles.Forsyth   /*                                                                       */
2968*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
Render_Glyph(RAS_ARG)2969*37da2899SCharles.Forsyth   Render_Glyph( RAS_ARG )
2970*37da2899SCharles.Forsyth   {
2971*37da2899SCharles.Forsyth     FT_Error  error;
2972*37da2899SCharles.Forsyth 
2973*37da2899SCharles.Forsyth 
2974*37da2899SCharles.Forsyth     Set_High_Precision( RAS_VARS ras.outline.flags &
2975*37da2899SCharles.Forsyth                         FT_OUTLINE_HIGH_PRECISION );
2976*37da2899SCharles.Forsyth     ras.scale_shift    = ras.precision_shift;
2977*37da2899SCharles.Forsyth     ras.dropOutControl = 2;
2978*37da2899SCharles.Forsyth     ras.second_pass    = (FT_Byte)( !( ras.outline.flags &
2979*37da2899SCharles.Forsyth                                        FT_OUTLINE_SINGLE_PASS ) );
2980*37da2899SCharles.Forsyth 
2981*37da2899SCharles.Forsyth     /* Vertical Sweep */
2982*37da2899SCharles.Forsyth     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
2983*37da2899SCharles.Forsyth     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
2984*37da2899SCharles.Forsyth     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
2985*37da2899SCharles.Forsyth     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
2986*37da2899SCharles.Forsyth 
2987*37da2899SCharles.Forsyth     ras.band_top            = 0;
2988*37da2899SCharles.Forsyth     ras.band_stack[0].y_min = 0;
2989*37da2899SCharles.Forsyth     ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
2990*37da2899SCharles.Forsyth 
2991*37da2899SCharles.Forsyth     ras.bWidth  = (unsigned short)ras.target.width;
2992*37da2899SCharles.Forsyth     ras.bTarget = (Byte*)ras.target.buffer;
2993*37da2899SCharles.Forsyth 
2994*37da2899SCharles.Forsyth     if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
2995*37da2899SCharles.Forsyth       return error;
2996*37da2899SCharles.Forsyth 
2997*37da2899SCharles.Forsyth     /* Horizontal Sweep */
2998*37da2899SCharles.Forsyth     if ( ras.second_pass && ras.dropOutControl != 0 )
2999*37da2899SCharles.Forsyth     {
3000*37da2899SCharles.Forsyth       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3001*37da2899SCharles.Forsyth       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3002*37da2899SCharles.Forsyth       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3003*37da2899SCharles.Forsyth       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3004*37da2899SCharles.Forsyth 
3005*37da2899SCharles.Forsyth       ras.band_top            = 0;
3006*37da2899SCharles.Forsyth       ras.band_stack[0].y_min = 0;
3007*37da2899SCharles.Forsyth       ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
3008*37da2899SCharles.Forsyth 
3009*37da2899SCharles.Forsyth       if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3010*37da2899SCharles.Forsyth         return error;
3011*37da2899SCharles.Forsyth     }
3012*37da2899SCharles.Forsyth 
3013*37da2899SCharles.Forsyth     return Raster_Err_Ok;
3014*37da2899SCharles.Forsyth   }
3015*37da2899SCharles.Forsyth 
3016*37da2899SCharles.Forsyth 
3017*37da2899SCharles.Forsyth #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3018*37da2899SCharles.Forsyth 
3019*37da2899SCharles.Forsyth 
3020*37da2899SCharles.Forsyth   /*************************************************************************/
3021*37da2899SCharles.Forsyth   /*                                                                       */
3022*37da2899SCharles.Forsyth   /* <Function>                                                            */
3023*37da2899SCharles.Forsyth   /*    Render_Gray_Glyph                                                  */
3024*37da2899SCharles.Forsyth   /*                                                                       */
3025*37da2899SCharles.Forsyth   /* <Description>                                                         */
3026*37da2899SCharles.Forsyth   /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
3027*37da2899SCharles.Forsyth   /*                                                                       */
3028*37da2899SCharles.Forsyth   /* <Return>                                                              */
3029*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
3030*37da2899SCharles.Forsyth   /*                                                                       */
3031*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
Render_Gray_Glyph(RAS_ARG)3032*37da2899SCharles.Forsyth   Render_Gray_Glyph( RAS_ARG )
3033*37da2899SCharles.Forsyth   {
3034*37da2899SCharles.Forsyth     Long      pixel_width;
3035*37da2899SCharles.Forsyth     FT_Error  error;
3036*37da2899SCharles.Forsyth 
3037*37da2899SCharles.Forsyth 
3038*37da2899SCharles.Forsyth     Set_High_Precision( RAS_VARS ras.outline.flags &
3039*37da2899SCharles.Forsyth                         FT_OUTLINE_HIGH_PRECISION );
3040*37da2899SCharles.Forsyth     ras.scale_shift    = ras.precision_shift + 1;
3041*37da2899SCharles.Forsyth     ras.dropOutControl = 2;
3042*37da2899SCharles.Forsyth     ras.second_pass    = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
3043*37da2899SCharles.Forsyth 
3044*37da2899SCharles.Forsyth     /* Vertical Sweep */
3045*37da2899SCharles.Forsyth 
3046*37da2899SCharles.Forsyth     ras.band_top            = 0;
3047*37da2899SCharles.Forsyth     ras.band_stack[0].y_min = 0;
3048*37da2899SCharles.Forsyth     ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
3049*37da2899SCharles.Forsyth 
3050*37da2899SCharles.Forsyth     ras.bWidth  = ras.gray_width;
3051*37da2899SCharles.Forsyth     pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
3052*37da2899SCharles.Forsyth 
3053*37da2899SCharles.Forsyth     if ( ras.bWidth > pixel_width )
3054*37da2899SCharles.Forsyth       ras.bWidth = pixel_width;
3055*37da2899SCharles.Forsyth 
3056*37da2899SCharles.Forsyth     ras.bWidth  = ras.bWidth * 8;
3057*37da2899SCharles.Forsyth     ras.bTarget = (Byte*)ras.gray_lines;
3058*37da2899SCharles.Forsyth     ras.gTarget = (Byte*)ras.target.buffer;
3059*37da2899SCharles.Forsyth 
3060*37da2899SCharles.Forsyth     ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
3061*37da2899SCharles.Forsyth     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3062*37da2899SCharles.Forsyth     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3063*37da2899SCharles.Forsyth     ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
3064*37da2899SCharles.Forsyth 
3065*37da2899SCharles.Forsyth     error = Render_Single_Pass( RAS_VARS 0 );
3066*37da2899SCharles.Forsyth     if ( error )
3067*37da2899SCharles.Forsyth       return error;
3068*37da2899SCharles.Forsyth 
3069*37da2899SCharles.Forsyth     /* Horizontal Sweep */
3070*37da2899SCharles.Forsyth     if ( ras.second_pass && ras.dropOutControl != 0 )
3071*37da2899SCharles.Forsyth     {
3072*37da2899SCharles.Forsyth       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3073*37da2899SCharles.Forsyth       ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
3074*37da2899SCharles.Forsyth       ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
3075*37da2899SCharles.Forsyth       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3076*37da2899SCharles.Forsyth 
3077*37da2899SCharles.Forsyth       ras.band_top            = 0;
3078*37da2899SCharles.Forsyth       ras.band_stack[0].y_min = 0;
3079*37da2899SCharles.Forsyth       ras.band_stack[0].y_max = ras.target.width * 2 - 1;
3080*37da2899SCharles.Forsyth 
3081*37da2899SCharles.Forsyth       error = Render_Single_Pass( RAS_VARS 1 );
3082*37da2899SCharles.Forsyth       if ( error )
3083*37da2899SCharles.Forsyth         return error;
3084*37da2899SCharles.Forsyth     }
3085*37da2899SCharles.Forsyth 
3086*37da2899SCharles.Forsyth     return Raster_Err_Ok;
3087*37da2899SCharles.Forsyth   }
3088*37da2899SCharles.Forsyth 
3089*37da2899SCharles.Forsyth #else /* !FT_RASTER_OPTION_ANTI_ALIASING */
3090*37da2899SCharles.Forsyth 
3091*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
Render_Gray_Glyph(RAS_ARG)3092*37da2899SCharles.Forsyth   Render_Gray_Glyph( RAS_ARG )
3093*37da2899SCharles.Forsyth   {
3094*37da2899SCharles.Forsyth     FT_UNUSED_RASTER;
3095*37da2899SCharles.Forsyth 
3096*37da2899SCharles.Forsyth     return Raster_Err_Cannot_Render_Glyph;
3097*37da2899SCharles.Forsyth   }
3098*37da2899SCharles.Forsyth 
3099*37da2899SCharles.Forsyth #endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
3100*37da2899SCharles.Forsyth 
3101*37da2899SCharles.Forsyth 
3102*37da2899SCharles.Forsyth   static void
ft_black_init(TRaster_Instance * raster)3103*37da2899SCharles.Forsyth   ft_black_init( TRaster_Instance*  raster )
3104*37da2899SCharles.Forsyth   {
3105*37da2899SCharles.Forsyth     FT_UInt  n;
3106*37da2899SCharles.Forsyth     FT_ULong c;
3107*37da2899SCharles.Forsyth 
3108*37da2899SCharles.Forsyth 
3109*37da2899SCharles.Forsyth     /* setup count table */
3110*37da2899SCharles.Forsyth     for ( n = 0; n < 256; n++ )
3111*37da2899SCharles.Forsyth     {
3112*37da2899SCharles.Forsyth       c = ( n & 0x55 ) + ( ( n & 0xAA ) >> 1 );
3113*37da2899SCharles.Forsyth 
3114*37da2899SCharles.Forsyth       c = ( ( c << 6 ) & 0x3000 ) |
3115*37da2899SCharles.Forsyth           ( ( c << 4 ) & 0x0300 ) |
3116*37da2899SCharles.Forsyth           ( ( c << 2 ) & 0x0030 ) |
3117*37da2899SCharles.Forsyth                    (c  & 0x0003 );
3118*37da2899SCharles.Forsyth 
3119*37da2899SCharles.Forsyth       raster->count_table[n] = (UInt)c;
3120*37da2899SCharles.Forsyth     }
3121*37da2899SCharles.Forsyth 
3122*37da2899SCharles.Forsyth #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3123*37da2899SCharles.Forsyth 
3124*37da2899SCharles.Forsyth     /* set default 5-levels gray palette */
3125*37da2899SCharles.Forsyth     for ( n = 0; n < 5; n++ )
3126*37da2899SCharles.Forsyth       raster->grays[n] = n * 255 / 4;
3127*37da2899SCharles.Forsyth 
3128*37da2899SCharles.Forsyth     raster->gray_width = RASTER_GRAY_LINES / 2;
3129*37da2899SCharles.Forsyth 
3130*37da2899SCharles.Forsyth #endif
3131*37da2899SCharles.Forsyth   }
3132*37da2899SCharles.Forsyth 
3133*37da2899SCharles.Forsyth 
3134*37da2899SCharles.Forsyth   /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3135*37da2899SCharles.Forsyth   /****                         a static object.                  *****/
3136*37da2899SCharles.Forsyth 
3137*37da2899SCharles.Forsyth 
3138*37da2899SCharles.Forsyth #ifdef _STANDALONE_
3139*37da2899SCharles.Forsyth 
3140*37da2899SCharles.Forsyth 
3141*37da2899SCharles.Forsyth   static int
ft_black_new(void * memory,FT_Raster * araster)3142*37da2899SCharles.Forsyth   ft_black_new( void*      memory,
3143*37da2899SCharles.Forsyth                 FT_Raster  *araster )
3144*37da2899SCharles.Forsyth   {
3145*37da2899SCharles.Forsyth      static FT_RasterRec_  the_raster;
3146*37da2899SCharles.Forsyth 
3147*37da2899SCharles.Forsyth 
3148*37da2899SCharles.Forsyth      *araster = &the_raster;
3149*37da2899SCharles.Forsyth      FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
3150*37da2899SCharles.Forsyth      ft_black_init( &the_raster );
3151*37da2899SCharles.Forsyth 
3152*37da2899SCharles.Forsyth      return 0;
3153*37da2899SCharles.Forsyth   }
3154*37da2899SCharles.Forsyth 
3155*37da2899SCharles.Forsyth 
3156*37da2899SCharles.Forsyth   static void
ft_black_done(FT_Raster raster)3157*37da2899SCharles.Forsyth   ft_black_done( FT_Raster  raster )
3158*37da2899SCharles.Forsyth   {
3159*37da2899SCharles.Forsyth     /* nothing */
3160*37da2899SCharles.Forsyth     raster->init = 0;
3161*37da2899SCharles.Forsyth   }
3162*37da2899SCharles.Forsyth 
3163*37da2899SCharles.Forsyth 
3164*37da2899SCharles.Forsyth #else /* _STANDALONE_ */
3165*37da2899SCharles.Forsyth 
3166*37da2899SCharles.Forsyth 
3167*37da2899SCharles.Forsyth   static int
ft_black_new(FT_Memory memory,TRaster_Instance ** araster)3168*37da2899SCharles.Forsyth   ft_black_new( FT_Memory           memory,
3169*37da2899SCharles.Forsyth                 TRaster_Instance**  araster )
3170*37da2899SCharles.Forsyth   {
3171*37da2899SCharles.Forsyth     FT_Error           error;
3172*37da2899SCharles.Forsyth     TRaster_Instance*  raster;
3173*37da2899SCharles.Forsyth 
3174*37da2899SCharles.Forsyth 
3175*37da2899SCharles.Forsyth     *araster = 0;
3176*37da2899SCharles.Forsyth     if ( !FT_NEW( raster ) )
3177*37da2899SCharles.Forsyth     {
3178*37da2899SCharles.Forsyth       raster->memory = memory;
3179*37da2899SCharles.Forsyth       ft_black_init( raster );
3180*37da2899SCharles.Forsyth 
3181*37da2899SCharles.Forsyth       *araster = raster;
3182*37da2899SCharles.Forsyth     }
3183*37da2899SCharles.Forsyth 
3184*37da2899SCharles.Forsyth     return error;
3185*37da2899SCharles.Forsyth   }
3186*37da2899SCharles.Forsyth 
3187*37da2899SCharles.Forsyth 
3188*37da2899SCharles.Forsyth   static void
ft_black_done(TRaster_Instance * raster)3189*37da2899SCharles.Forsyth   ft_black_done( TRaster_Instance*  raster )
3190*37da2899SCharles.Forsyth   {
3191*37da2899SCharles.Forsyth     FT_Memory  memory = (FT_Memory)raster->memory;
3192*37da2899SCharles.Forsyth     FT_FREE( raster );
3193*37da2899SCharles.Forsyth   }
3194*37da2899SCharles.Forsyth 
3195*37da2899SCharles.Forsyth 
3196*37da2899SCharles.Forsyth #endif /* _STANDALONE_ */
3197*37da2899SCharles.Forsyth 
3198*37da2899SCharles.Forsyth 
3199*37da2899SCharles.Forsyth   static void
ft_black_reset(TRaster_Instance * raster,const char * pool_base,long pool_size)3200*37da2899SCharles.Forsyth   ft_black_reset( TRaster_Instance*  raster,
3201*37da2899SCharles.Forsyth                   const char*        pool_base,
3202*37da2899SCharles.Forsyth                   long               pool_size )
3203*37da2899SCharles.Forsyth   {
3204*37da2899SCharles.Forsyth     if ( raster && pool_base && pool_size >= 4096 )
3205*37da2899SCharles.Forsyth     {
3206*37da2899SCharles.Forsyth       /* save the pool */
3207*37da2899SCharles.Forsyth       raster->buff     = (PLong)pool_base;
3208*37da2899SCharles.Forsyth       raster->sizeBuff = raster->buff + pool_size / sizeof ( Long );
3209*37da2899SCharles.Forsyth     }
3210*37da2899SCharles.Forsyth   }
3211*37da2899SCharles.Forsyth 
3212*37da2899SCharles.Forsyth 
3213*37da2899SCharles.Forsyth   static void
ft_black_set_mode(TRaster_Instance * raster,unsigned long mode,const char * palette)3214*37da2899SCharles.Forsyth   ft_black_set_mode( TRaster_Instance*  raster,
3215*37da2899SCharles.Forsyth                      unsigned long      mode,
3216*37da2899SCharles.Forsyth                      const char*        palette )
3217*37da2899SCharles.Forsyth   {
3218*37da2899SCharles.Forsyth #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3219*37da2899SCharles.Forsyth 
3220*37da2899SCharles.Forsyth     if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
3221*37da2899SCharles.Forsyth     {
3222*37da2899SCharles.Forsyth       /* set 5-levels gray palette */
3223*37da2899SCharles.Forsyth       raster->grays[0] = palette[0];
3224*37da2899SCharles.Forsyth       raster->grays[1] = palette[1];
3225*37da2899SCharles.Forsyth       raster->grays[2] = palette[2];
3226*37da2899SCharles.Forsyth       raster->grays[3] = palette[3];
3227*37da2899SCharles.Forsyth       raster->grays[4] = palette[4];
3228*37da2899SCharles.Forsyth     }
3229*37da2899SCharles.Forsyth 
3230*37da2899SCharles.Forsyth #else
3231*37da2899SCharles.Forsyth 
3232*37da2899SCharles.Forsyth     FT_UNUSED( raster );
3233*37da2899SCharles.Forsyth     FT_UNUSED( mode );
3234*37da2899SCharles.Forsyth     FT_UNUSED( palette );
3235*37da2899SCharles.Forsyth 
3236*37da2899SCharles.Forsyth #endif
3237*37da2899SCharles.Forsyth   }
3238*37da2899SCharles.Forsyth 
3239*37da2899SCharles.Forsyth 
3240*37da2899SCharles.Forsyth   static int
ft_black_render(TRaster_Instance * raster,FT_Raster_Params * params)3241*37da2899SCharles.Forsyth   ft_black_render( TRaster_Instance*  raster,
3242*37da2899SCharles.Forsyth                    FT_Raster_Params*  params )
3243*37da2899SCharles.Forsyth   {
3244*37da2899SCharles.Forsyth     FT_Outline*  outline    = (FT_Outline*)params->source;
3245*37da2899SCharles.Forsyth     FT_Bitmap*   target_map = params->target;
3246*37da2899SCharles.Forsyth 
3247*37da2899SCharles.Forsyth 
3248*37da2899SCharles.Forsyth     if ( !raster || !raster->buff || !raster->sizeBuff )
3249*37da2899SCharles.Forsyth       return Raster_Err_Not_Ini;
3250*37da2899SCharles.Forsyth 
3251*37da2899SCharles.Forsyth     /* return immediately if the outline is empty */
3252*37da2899SCharles.Forsyth     if ( outline->n_points == 0 || outline->n_contours <= 0 )
3253*37da2899SCharles.Forsyth       return Raster_Err_None;
3254*37da2899SCharles.Forsyth 
3255*37da2899SCharles.Forsyth     if ( !outline || !outline->contours || !outline->points )
3256*37da2899SCharles.Forsyth       return Raster_Err_Invalid;
3257*37da2899SCharles.Forsyth 
3258*37da2899SCharles.Forsyth     if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
3259*37da2899SCharles.Forsyth       return Raster_Err_Invalid;
3260*37da2899SCharles.Forsyth 
3261*37da2899SCharles.Forsyth     /* this version of the raster does not support direct rendering, sorry */
3262*37da2899SCharles.Forsyth     if ( params->flags & FT_RASTER_FLAG_DIRECT )
3263*37da2899SCharles.Forsyth       return Raster_Err_Unsupported;
3264*37da2899SCharles.Forsyth 
3265*37da2899SCharles.Forsyth     if ( !target_map || !target_map->buffer )
3266*37da2899SCharles.Forsyth       return Raster_Err_Invalid;
3267*37da2899SCharles.Forsyth 
3268*37da2899SCharles.Forsyth     ras.outline  = *outline;
3269*37da2899SCharles.Forsyth     ras.target   = *target_map;
3270*37da2899SCharles.Forsyth 
3271*37da2899SCharles.Forsyth     return ( ( params->flags & FT_RASTER_FLAG_AA )
3272*37da2899SCharles.Forsyth                ? Render_Gray_Glyph( raster )
3273*37da2899SCharles.Forsyth                : Render_Glyph( raster ) );
3274*37da2899SCharles.Forsyth   }
3275*37da2899SCharles.Forsyth 
3276*37da2899SCharles.Forsyth 
3277*37da2899SCharles.Forsyth   const FT_Raster_Funcs  ft_standard_raster =
3278*37da2899SCharles.Forsyth   {
3279*37da2899SCharles.Forsyth     FT_GLYPH_FORMAT_OUTLINE,
3280*37da2899SCharles.Forsyth     (FT_Raster_New_Func)     ft_black_new,
3281*37da2899SCharles.Forsyth     (FT_Raster_Reset_Func)   ft_black_reset,
3282*37da2899SCharles.Forsyth     (FT_Raster_Set_Mode_Func)ft_black_set_mode,
3283*37da2899SCharles.Forsyth     (FT_Raster_Render_Func)  ft_black_render,
3284*37da2899SCharles.Forsyth     (FT_Raster_Done_Func)    ft_black_done
3285*37da2899SCharles.Forsyth   };
3286*37da2899SCharles.Forsyth 
3287*37da2899SCharles.Forsyth 
3288*37da2899SCharles.Forsyth /* END */
3289