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