ftraster.c revision 174b8de3283c921d8bddf48325fe42ba7330a930
1a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/***************************************************************************/
2a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
3a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  ftraster.c                                                             */
4a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
5a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*    The FreeType glyph rasterizer (body).                                */
6a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
7eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg/*  Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008 by                   */
8a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
10a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  This file is part of the FreeType project, and may only be used,       */
11a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  modified, and distributed under the terms of the FreeType project      */
12a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  this file you indicate that you have read the license and              */
14a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  understand and accept it fully.                                        */
15a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
16a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/***************************************************************************/
17a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
18a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
19a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
20f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* This file can be compiled without the rest of the FreeType engine, by */
21f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
22f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
23f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* directory.  Typically, you should do something like                   */
24f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
25f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
26f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
27f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */
28f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*   to your current directory                                           */
29f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
30f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
31f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
32f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*     cc -c -D_STANDALONE_ ftraster.c                                   */
33f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
34f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* The renderer can be initialized with a call to                        */
35f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
36f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* with a call to `ft_standard_raster.raster_render'.                    */
37f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
38f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* See the comments and documentation in the file `ftimage.h' for more   */
39f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /* details on how the raster works.                                      */
40f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
41f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*************************************************************************/
42f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
43f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
44f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*************************************************************************/
45f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
46a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* This is a rewrite of the FreeType 1.x scan-line converter             */
47a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
48a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
49a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
50f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef _STANDALONE_
51f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
52f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftmisc.h"
53f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftimage.h"
54f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
55f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#else /* !_STANDALONE_ */
56a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5719ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include <ft2build.h>
588d3a401fa808a8c70bd6a9ce17d5a840fb0ae2dbDavid Turner#include "ftraster.h"
5919ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
60a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
61f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif /* !_STANDALONE_ */
62f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
63a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
64a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
65a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
66a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A simple technical note on how the raster works                       */
67a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* -----------------------------------------------                       */
68a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
69a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Converting an outline into a bitmap is achieved in several steps:   */
70a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
71a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
72a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       profile is simply an array of scanline intersections on a given */
73a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       dimension.  A profile's main attributes are                     */
74a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
75a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
76a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
77a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o an array of intersection coordinates for each scanline        */
78a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*         between `Ymin' and `Ymax'.                                    */
79a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
80a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o a direction, indicating whether it was built going `up' or    */
81a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*         `down', as this is very important for filling rules.          */
82a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
83a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   2 - Sweeping the target map's scanlines in order to compute segment */
84a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       `spans' which are then filled.  Additionally, this pass         */
85a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       performs drop-out control.                                      */
86a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
87a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The outline data is parsed during step 1 only.  The profiles are    */
88a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the bottom of the render pool, used as a stack.  The     */
89a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   following graphics shows the profile list under construction:       */
90a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
91a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*     ____________________________________________________________ _ _  */
92a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    |         |                   |         |                 |        */
93a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    | profile | coordinates for   | profile | coordinates for |-->     */
94a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
95a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    |_________|___________________|_________|_________________|__ _ _  */
96a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
97a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    ^                                                         ^        */
98a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    |                                                         |        */
99a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  start of render pool                                       top       */
100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The top of the profile stack is kept in the `top' variable.         */
102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   As you can see, a profile record is pushed on top of the render     */
104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   pool, which is then followed by its coordinates/intersections.  If  */
105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   a change of direction is detected in the outline, a new profile is  */
106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   generated until the end of the outline.                             */
107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Note that when all profiles have been generated, the function       */
109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   bottom-most scanline as well as the scanline above its upmost       */
111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   boundary.  These positions are called `y-turns' because they (sort  */
112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   of) correspond to local extrema.  They are stored in a sorted list  */
113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the top of the render pool as a downwards stack:         */
114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ _______________________________________                      */
116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--| sorted list of     |                     */
118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--|  extrema scanlines |                     */
119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ __________________|____________________|                     */
120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            ^                    ^                     */
122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         maxBuff           sizeBuff = end of pool      */
124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   This list is later used during the sweep phase in order to          */
126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   optimize performance (see technical note on the sweep below).       */
127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Of course, the raster detects whether the two stacks collide and    */
1296e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg  /*   handles the situation properly.                                     */
130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  CONFIGURATION MACROS                                               **/
138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* define DEBUG_RASTER if you want to compile a debugging version */
143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define xxxDEBUG_RASTER
144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* 5-levels anti-aliasing                                                */
147eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg#undef FT_RASTER_OPTION_ANTI_ALIASING
148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The size of the two-lines intermediate bitmap used */
150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* for anti-aliasing, in bytes.                       */
151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RASTER_GRAY_LINES  2048
152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  OTHER MACROS (do not change)                                       **/
158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* messages during execution.                                            */
167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  FT_COMPONENT
169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_COMPONENT  trace_raster
170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef _STANDALONE_
173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* This macro is used to indicate that a function parameter is unused. */
176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* ANSI compilers (e.g. LCC).                                          */
179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_UNUSED( x )  (x) = (x)
180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Disable the tracing mechanism for simplicity -- developers can      */
182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* activate it easily by redefining these two macros.                  */
183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_ERROR
184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_TRACE
188f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_TRACE( x )   do ; while ( 0 )    /* nothing */
189f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_TRACE1( x )  do ; while ( 0 )    /* nothing */
190f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_TRACE6( x )  do ; while ( 0 )    /* nothing */
191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_None          0
194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Not_Ini      -1
195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Overflow     -2
196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Neg_Height   -3
197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Invalid      -4
198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Unsupported  -5
199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
200f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define ft_memset   memset
201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else /* _STANDALONE_ */
203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2051f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include FT_INTERNAL_OBJECTS_H
2061f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2081f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include "rasterrs.h"
2091f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg
2101f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_None         Raster_Err_Ok
2111f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
2121f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
2131f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
2141f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
2151f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* _STANDALONE_ */
219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
221e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner#ifndef FT_MEM_SET
222d15bc0d13a163995e1ca11925349bd64d1c33617David Turner#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
223c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg#endif
224c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
225f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifndef FT_MEM_ZERO
226f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
227f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif
228c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
230a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* typically a small value and the result of a*b is known to fit into */
231a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* 32 bits.                                                           */
232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* defined in `ftcalc.h'.                                                */
237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SMulDiv  FT_MulDiv
238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The rasterizer is a very general purpose component; please leave */
240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* the following redefinitions there (you never know your target    */
241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* environment).                                                    */
242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef TRUE
244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define TRUE   1
245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FALSE
248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FALSE  0
249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef NULL
252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define NULL  (void*)0
253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef SUCCESS
256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SUCCESS  0
257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FAILURE
260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FAILURE  1
261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* Setting this constant to more than 32 is a   */
266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* pure waste of space.                         */
267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SIMPLE TYPE DECLARATIONS                                           **/
275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef int             Int;
280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned int    UInt;
281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef short           Short;
282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned short  UShort, *PUShort;
283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef long            Long, *PLong;
284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned long   ULong;
285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned char   Byte, *PByte;
287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef char            Bool;
288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
289fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
290fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg  typedef union  Alignment_
2918530a228889128adfd446514928f36663ed20f04David Turner  {
2928530a228889128adfd446514928f36663ed20f04David Turner    long    l;
2938530a228889128adfd446514928f36663ed20f04David Turner    void*   p;
2948530a228889128adfd446514928f36663ed20f04David Turner    void  (*f)(void);
2958530a228889128adfd446514928f36663ed20f04David Turner
2968530a228889128adfd446514928f36663ed20f04David Turner  } Alignment, *PAlignment;
2978530a228889128adfd446514928f36663ed20f04David Turner
298fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct  TPoint_
300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  x;
302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  y;
303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TPoint;
305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef enum  TFlow_
308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Flow_None = 0,
310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Flow_Up   = 1,
311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Flow_Down = -1
312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TFlow;
314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* States of each line, arc, and profile */
317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef enum  TStates_
318a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3199ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Unknown_State,
3209ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Ascending_State,
3219ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Descending_State,
3229ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Flat_State
323a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TStates;
325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct TProfile_  TProfile;
328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef TProfile*         PProfile;
329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  struct  TProfile_
331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_F26Dot6  X;           /* current coordinate during sweep        */
333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile    link;        /* link to next profile - various purpose */
334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong       offset;      /* start of profile's data in render pool */
3358edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    int         flow;        /* Profile orientation: Asc/Descending    */
3368edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    long        height;      /* profile's height in scanlines          */
3378edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    long        start;       /* profile's starting scanline            */
338a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3398edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    unsigned    countL;      /* number of lines to step before this    */
340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                             /* profile becomes drawable               */
341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile    next;        /* next profile in same contour, used     */
343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                             /* during drop-out control                */
344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  };
345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile   TProfileList;
347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile*  PProfileList;
348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
349a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Simple record used to implement a stack of bands, required */
351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* by the sub-banding mechanism                               */
352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct  TBand_
353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_min;   /* band's minimum */
355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_max;   /* band's maximum */
356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TBand;
358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define AlignProfileSize \
361fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
363a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
364f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARGS       /* void */
368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARG        /* void */
369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VARS       /* void */
371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VAR        /* void */
372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_UNUSED_RASTER  do ; while ( 0 )
374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
376f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#else /* FT_STATIC_RASTER */
377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3798a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_ARGS       PWorker    worker,
3808a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_ARG        PWorker    worker
381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3828a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VARS       worker,
3838a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VAR        worker
384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3858a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define FT_UNUSED_RASTER  FT_UNUSED( worker )
386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
388f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif /* FT_STATIC_RASTER */
389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
391174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  typedef struct TWorker_  TWorker, *PWorker;
392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* prototypes used for sweep function dispatch */
39552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
39652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Init( RAS_ARGS Short*  min,
39752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max );
398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
39952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
40052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Span( RAS_ARGS Short       y,
40152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
40252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
40352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
40452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right );
405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
40652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
40752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Step( RAS_ARG );
408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* NOTE: These operations are only valid on 2's complement processors */
411a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
412a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FLOOR( x )    ( (x) & -ras.precision )
413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
415a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Note that I have moved the location of some fields in the */
419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* structure to ensure that the most used variables are used */
420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* at the top.  Thus, their offset can be coded with less    */
421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* opcodes, and it results in a smaller executable.          */
422a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4238a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  struct  TWorker_
424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision_bits;       /* precision related variables         */
426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision;
427a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision_half;
428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      precision_mask;
429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision_shift;
430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision_step;
431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       precision_jitter;
432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       scale_shift;          /* == precision_shift   for bitmaps    */
434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* == precision_shift+1 for pixmaps    */
435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong     buff;                 /* The profiles buffer                 */
437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong     sizeBuff;             /* Render pool size                    */
438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong     maxBuff;              /* Profiles buffer size                */
439a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong     top;                  /* Current cursor in buffer            */
440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       numTurns;             /* number of Y-turns in outline        */
444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*   arc;                  /* current Bezier arc pointer          */
446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    UShort    bWidth;               /* target bitmap width                 */
448a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte     bTarget;              /* target bitmap buffer                */
449a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte     gTarget;              /* target pixmap buffer                */
450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      lastX, lastY, minY, maxY;
452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    UShort    num_Profs;            /* current number of profiles          */
454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
455a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool      fresh;                /* signals a fresh new profile which   */
456a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* 'start' field must be completed     */
457a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool      joint;                /* signals that the last arc ended     */
458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* exactly on a scanline.  Allows      */
459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* removal of doublets                 */
460a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  cProfile;             /* current profile                     */
461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  fProfile;             /* head of linked list of profiles     */
462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  gProfile;             /* contour's first profile in case     */
463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* of impact                           */
464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates   state;                /* rendering state                     */
466a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
467a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Bitmap   target;             /* description of target bit/pixmap    */
468a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Outline  outline;
469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
470a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      traceOfs;             /* current offset in target bitmap     */
471a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      traceG;               /* current offset in target pixmap     */
472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short     traceIncr;            /* sweep's increment in target bitmap  */
474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short     gray_min_x;           /* current min x during gray rendering */
476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short     gray_max_x;           /* current max x during gray rendering */
477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* dispatch variables */
479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Init*  Proc_Sweep_Init;
481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Span;
482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Drop;
483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Step*  Proc_Sweep_Step;
484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte      dropOutControl;       /* current drop_out control method     */
486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4876e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg    Bool      second_pass;          /* indicates whether a horizontal pass */
488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* should be performed to control      */
489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* drop-out accurately when calling    */
490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* Render_Glyph.  Note that there is   */
491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* no horizontal pass during gray      */
492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* rendering.                          */
493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
494caf72cd6e5765aa5419f2f3e8e42610181dc82e8David Turner    TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */
495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TBand     band_stack[16];       /* band stack used for sub-banding     */
497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       band_top;             /* band stack top                      */
498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5018a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    Byte*     grays;
502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte      gray_lines[RASTER_GRAY_LINES];
504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* Intermediate table used to render the   */
505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* graylevels pixmaps.                     */
506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* gray_lines is a buffer holding two      */
507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* monochrome scanlines                    */
508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short     gray_width;       /* width in bytes of one monochrome        */
510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* intermediate scanline of gray_lines.    */
511a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* Each gray pixel takes 2 bits long there */
512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       /* The gray_lines must hold 2 lines, thus with size */
514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       /* in bytes of at least `gray_width*2'.             */
515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* FT_RASTER_ANTI_ALIASING */
517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5188a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  };
519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
521174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  typedef struct  TRaster_
5228a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  {
5238a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    char*     buffer;
5248a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    long      buffer_size;
5258a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    void*     memory;
5268a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    PWorker   worker;
5278a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    Byte      grays[5];
5288a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    Short     gray_width;
529a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5308a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  } TRaster, *PRaster;
531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
532f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
533a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
534174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  static TWorker  cur_ras;
535a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define ras  cur_ras
536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else
538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5398a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define ras  (*worker)
540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
541f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif /* FT_STATIC_RASTER */
542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
54439c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg#ifdef FT_RASTER_OPTION_ANTI_ALIASING
54539c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg
546174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  static const char  count_table[256] =
547174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  {
548174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,
549174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
550174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
551174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
552174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
553174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
554174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
555174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
556174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
557174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
558174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
559174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
560174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
561174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
562174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
563174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8
564174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberga  };
56538d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
56639c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
56739c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg
56838d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
56938d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  PROFILES COMPUTATION                                               **/
574a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
579a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Set_High_Precision                                                 */
583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
585174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Set precision variables according to param flag.                   */
586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
587a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
588a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    High :: Set to True for high precision (typically for ppem < 18),  */
589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*            false otherwise.                                           */
590a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
59152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
59252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Set_High_Precision( RAS_ARGS Int  High )
593a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
594a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( High )
595a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
596a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_bits   = 10;
597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_step   = 128;
598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_jitter = 24;
599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_bits   = 6;
603a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_step   = 32;
604a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_jitter = 2;
605a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
606a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
607a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
608a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
60968e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg    ras.precision       = 1 << ras.precision_bits;
610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_half  = ras.precision / 2;
611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_shift = ras.precision_bits - Pixel_Bits;
612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_mask  = -ras.precision;
613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New_Profile                                                        */
620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
622174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Create a new profile in the render pool.                           */
623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    aState :: The state/orientation of the new profile.                */
626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
63152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
63252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  New_Profile( RAS_ARGS TStates  aState )
633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.fProfile )
635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile  = (PProfile)ras.top;
637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile  = ras.cProfile;
638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top      += AlignProfileSize;
639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( aState )
648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
6499ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->flow = Flow_Up;
651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
652a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
6549ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->flow = Flow_Down;
656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Invalid;
662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->start  = 0;
666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->height = 0;
667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->offset = ras.top;
668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->link   = (PProfile)0;
669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->next   = (PProfile)0;
670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.gProfile )
672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = ras.cProfile;
673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.state = aState;
675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh = TRUE;
676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    End_Profile                                                        */
686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
688174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Finalize the current profile.                                      */
689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
69352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
69452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  End_Profile( RAS_ARG )
695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      h;
697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  oldProfile;
698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
700914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg    h = (Long)( ras.top - ras.cProfile->offset );
701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h < 0 )
703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_ERROR(( "End_Profile: negative height encountered!\n" ));
705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Neg_Height;
706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h > 0 )
710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                  (long)ras.cProfile, ras.cProfile->start, h ));
713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
714a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      oldProfile           = ras.cProfile;
715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = h;
716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile         = (PProfile)ras.top;
717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top             += AlignProfileSize;
719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = 0;
721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->offset = ras.top;
722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      oldProfile->next     = ras.cProfile;
723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.num_Profs++;
724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE1(( "overflow in End_Profile\n" ));
729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Insert_Y_Turn                                                      */
743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
745174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Insert a salient into the sorted list placed on top of the render  */
746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    pool.                                                              */
747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New y scanline position.                                           */
750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
75452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
75552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Insert_Y_Turn( RAS_ARGS Int  y )
756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
75751daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg    PLong  y_turns;
75851daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg    Int    y2, n;
759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n       = ras.numTurns - 1;
762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_turns = ras.sizeBuff - ras.numTurns;
763a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
764a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* look for first y value that is <= */
765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( n >= 0 && y < y_turns[n] )
766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      n--;
767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* if it is <, simply insert it, ignore if == */
769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n >= 0 && y > y_turns[n] )
770a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( n >= 0 )
771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
77268e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg        y2 = (Int)y_turns[n];
773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y_turns[n] = y;
774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y = y2;
775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        n--;
776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n < 0 )
779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
78051daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg      ras.maxBuff--;
781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.maxBuff <= ras.top )
782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
783a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.error = Raster_Err_Overflow;
784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns++;
787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.sizeBuff[-ras.numTurns] = y;
788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Finalize_Profile_Table                                             */
798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
799a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
800174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Adjust all links in the profiles list.                             */
801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
80552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
80652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Finalize_Profile_Table( RAS_ARG )
807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       bottom, top;
809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    UShort    n;
810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  p;
811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n = ras.num_Profs;
814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
815a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n > 1 )
816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      p = ras.fProfile;
818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( n > 0 )
819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( n > 1 )
821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = (PProfile)( p->offset + p->height );
822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = NULL;
824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        switch ( p->flow )
826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        case Flow_Down:
82868e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          bottom     = (Int)( p->start - p->height + 1 );
82968e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          top        = (Int)p->start;
830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->start   = bottom;
831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->offset += p->height - 1;
832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        case Flow_Up:
835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        default:
83668e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          bottom = (Int)p->start;
83768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          top    = (Int)( p->start + p->height - 1 );
838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( Insert_Y_Turn( RAS_VARS bottom )   ||
841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner             Insert_Y_Turn( RAS_VARS top + 1 )  )
842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        p = p->link;
845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        n--;
846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile = NULL;
850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Conic                                                        */
859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
861174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide one conic Bezier into two joint sub-arcs in the Bezier   */
862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    stack.                                                             */
863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    None (subdivided Bezier is taken from the top of the stack).       */
866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    loop that should be optimized to hell to get the best performance. */
870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
87152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
87252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Conic( TPoint*  base )
873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b;
875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = base[2].x;
878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x;
879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].x = ( base[2].x + b ) / 2;
880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x = ( base[0].x + b ) / 2;
881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = ( a + b ) / 2;
882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = base[2].y;
884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y;
885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].y = ( base[2].y + b ) / 2;
886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y = ( base[0].y + b ) / 2;
887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = ( a + b ) / 2;
888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* hand optimized.  gcc doesn't seem to be too good at common      */
890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* expression substitution and instruction scheduling ;-)          */
891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Cubic                                                        */
898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
900174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide a third-order Bezier arc into two joint sub-arcs in the  */
901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier stack.                                                      */
902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of the component.  It is one of _the_   */
905a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    inner loops that should be optimized like hell to get the best     */
906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    performance.                                                       */
907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
90852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
90952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Cubic( TPoint*  base )
910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b, c, d;
912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].x = base[3].x;
915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].x;
916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].x;
917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = a = ( a + c + 1 ) >> 1;
921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = b = ( b + c + 1 ) >> 1;
922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].x = ( a + b + 1 ) >> 1;
923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].y = base[3].y;
925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].y;
926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].y;
927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = a = ( a + c + 1 ) >> 1;
931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = b = ( b + c + 1 ) >> 1;
932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].y = ( a + b + 1 ) >> 1;
933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Up                                                            */
940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
942174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending line segment and store   */
943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
96152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
96252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Up( RAS_ARGS Long  x1,
96352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y1,
96452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  x2,
96552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y2,
96652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  miny,
96752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  maxy )
968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Dx, Dy;
970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Ix, Rx, Ax;
972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong  top;
974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dx = x2 - x1;
977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dy = y2 - y1;
978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dy <= 0 || y2 < miny || y1 > maxy )
980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return SUCCESS;
981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* Take care: miny-y1 can be a very large value; we use     */
985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /*            a slow MulDiv function to avoid clipping bugs */
986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += SMulDiv( Dx, miny - y1, Dy );
98773861976779a754cc9b808760cc8e6cf98d52549Werner Lemberg      e1  = (Int)TRUNC( miny );
988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f1  = 0;
989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
99268e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e1 = (Int)TRUNC( y1 );
99368e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f1 = (Int)FRAC( y1 );
994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 > maxy )
997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
99968e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2  = (Int)TRUNC( maxy );
1000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f2  = 0;
1001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1003a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
100468e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2 = (Int)TRUNC( y2 );
100568e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f2 = (Int)FRAC( y2 );
1006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( f1 > 0 )
1009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
1011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return SUCCESS;
1012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
1015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 += 1;
1016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.joint )
1020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.top--;
1022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.joint = FALSE;
1023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
10258edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    ras.joint = (char)( f2 == 0 );
1026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = e1;
1030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh           = FALSE;
1031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    size = e2 - e1 + 1;
1034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top + size >= ras.maxBuff )
1035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
1037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dx > 0 )
1041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ix = ( ras.precision * Dx ) / Dy;
1043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Rx = ( ras.precision * Dx ) % Dy;
1044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = 1;
1045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1046a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ix = -( ( ras.precision * -Dx ) / Dy );
1049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Rx =    ( ras.precision * -Dx ) % Dy;
1050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = -1;
1051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Ax  = -Dy;
1054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( size > 0 )
1057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *top++ = x1;
1059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += Ix;
1061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ax += Rx;
1062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Ax >= 0 )
1063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Ax -= Dy;
1065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        x1 += Dx;
1066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      size--;
1068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top = top;
1071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1073a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Down                                                          */
1079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1081174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending line segment and store  */
1082174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    them in the render pool.                                           */
1083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
1086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
1088a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
1090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
1092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
1094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
1096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
110052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
110152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Down( RAS_ARGS Long  x1,
110252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y1,
110352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  x2,
110452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y2,
110552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  miny,
110652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  maxy )
1107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool  result, fresh;
1109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh  = ras.fresh;
1112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A function type describing the functions used to split Bezier arcs */
1123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef void  (*TSplitter)( TPoint*  base );
1124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Up                                                          */
1130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1132174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending Bezier arc and store     */
1133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
114752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
114852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Up( RAS_ARGS Int        degree,
114952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      TSplitter  splitter,
115052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       miny,
115152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       maxy )
1152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   y1, y2, e, e2, e0;
1154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  f1;
1155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc;
1157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  start_arc;
1158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong top;
1160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc = ras.arc;
1163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y1  = arc[degree].y;
1164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y2  = arc[0].y;
1165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 < miny || y1 > maxy )
1168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e2 = FLOOR( y2 );
1171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 > maxy )
1173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = maxy;
1174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e0 = miny;
1176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
1178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e = miny;
1179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e  = CEILING( y1 );
1182914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( FRAC( y1 ) );
1183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e0 = e;
1184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( f1 == 0 )
1186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.joint )
1188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          top--;
1190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint = FALSE;
1191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *top++ = arc[degree].x;
1194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e += ras.precision;
1196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = TRUNC( e0 );
1202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh = FALSE;
1203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 < e )
1206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top   = top;
1211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
1212a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1213a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1214a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1215a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start_arc = arc;
1216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( arc >= start_arc && e <= e2 )
1218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.joint = FALSE;
1220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = arc[0].y;
1222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 > e )
1224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y1 = arc[degree].y;
1226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 - y1 >= ras.precision_step )
1227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          splitter( arc );
1229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc += degree;
1230a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1231a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
1234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                            e - y1, y2 - y1 );
1235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc -= degree;
1236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e   += ras.precision;
1237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 == e )
1242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint  = TRUE;
1244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *top++     = arc[0].x;
1245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e += ras.precision;
1247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        arc -= degree;
1249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fin:
1253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top  = top;
1254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc -= degree;
1255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Down                                                        */
1263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1265174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending Bezier arc and store    */
1266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
128052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
128152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Down( RAS_ARGS Int        degree,
128252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        TSplitter  splitter,
128352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       miny,
128452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       maxy )
1285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc = ras.arc;
1287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool     result, fresh;
1288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[1].y = -arc[1].y;
1292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[2].y = -arc[2].y;
1293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( degree > 2 )
1294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      arc[3].y = -arc[3].y;
1295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh = ras.fresh;
1297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_To                                                            */
1312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1314174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new line segment and adjust the Profiles list.            */
1315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x :: The x-coordinate of the segment's end point (its start point   */
1318ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastX').                                         */
1319a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y :: The y-coordinate of the segment's end point (its start point   */
1321ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastY').                                         */
1322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1323a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
132752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
132852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_To( RAS_ARGS Long  x,
132952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y )
1330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, detect a change of direction */
1332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
13359ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Unknown_State:
1336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
13389ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( New_Profile( RAS_VARS Ascending_State ) )
1339a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < ras.lastY )
13449ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg          if ( New_Profile( RAS_VARS Descending_State ) )
1345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return FAILURE;
1346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
13499ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y < ras.lastY )
1351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
13529ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( End_Profile( RAS_VAR )                   ||
13539ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg             New_Profile( RAS_VARS Descending_State ) )
1354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
13589ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
13619ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( End_Profile( RAS_VAR )                  ||
13629ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg             New_Profile( RAS_VARS Ascending_State ) )
1363a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1364a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then compute the lines */
1372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
13759ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
1377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                    x, y, ras.minY, ras.maxY ) )
1378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
13819ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1382a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
1383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                      x, y, ras.minY, ras.maxY ) )
1384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x;
1392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y;
1393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1395a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1396a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1397a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1399a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Conic_To                                                           */
1402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1403a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1404174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new conic arc and adjust the profile list.                */
1405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1406a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1407a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx :: The x-coordinate of the arc's new control point.              */
1408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy :: The y-coordinate of the arc's new control point.              */
1410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1411a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
1412ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastX').                                           */
1413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
1415ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastY').                                           */
1416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
142152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
142252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Conic_To( RAS_ARGS Long  cx,
142352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy,
142452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
142552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1427a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, x3, ymin, ymax;
1428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].x = ras.lastX;
1433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].y = ras.lastY;
1434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[1].x = cx; ras.arc[1].y = cy;
1435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[0].x = x;  ras.arc[0].y = y;
1436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1439a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[2].y;
1440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[1].y;
1441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[0].y;
1442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x3 = ras.arc[0].x;
1443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y3 )
1447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1448a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y1;
1449a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y3;
1450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y3;
1454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y1;
1455a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1456a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1457a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 < ymin || y2 > ymax )
1458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1460a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Conic( ras.arc );
1461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 2;
1462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y3 )
1464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1466a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 2;
1467a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1468a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1470a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the arc is y-monotonous, either ascending or descending */
1471a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction                            */
14729ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = y1 < y3 ? Ascending_State : Descending_State;
1473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* finalize current profile if any */
14769ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg          if ( ras.state != Unknown_State   &&
1477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner               End_Profile( RAS_VAR ) )
1478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* create a new profile */
1481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( New_Profile( RAS_VARS state_bez ) )
1482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* now call the appropriate routine */
14869ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x3;
1499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y3;
1500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1511a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Cubic_To                                                           */
1512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1514174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new cubic arc and adjust the profile list.                */
1515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
1518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
1520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1521a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
1522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1523a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
1524a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1525a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
1526ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastX').                                          */
1527a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
1529ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastY').                                          */
1530a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1533a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1534a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
153552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
153652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Cubic_To( RAS_ARGS Long  cx1,
153752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy1,
153852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cx2,
153952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy2,
154052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
154152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1544a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1545a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1546a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1548a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].x = ras.lastX;
1549a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].y = ras.lastY;
1550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].x = cx1; ras.arc[2].y = cy1;
1551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[1].x = cx2; ras.arc[1].y = cy2;
1552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[0].x = x;   ras.arc[0].y = y;
1553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1554a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1556a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[3].y;
1557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[2].y;
1558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[1].y;
1559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y4 = ras.arc[0].y;
1560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x4 = ras.arc[0].x;
1561a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1564a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y4 )
1565a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1566a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y1;
1567a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y4;
1568a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1569a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y4;
1572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y1;
1573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1574a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 <= y3 )
1576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y2;
1578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y3;
1579a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y3;
1583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y2;
1584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1585a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ymin2 < ymin1 || ymax2 > ymax1 )
1587a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1588a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Cubic( ras.arc );
1590a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 3;
1591a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1592a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y4 )
1593a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1594a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1595a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 3;
1596a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
15999ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction */
1602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1603a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
16049ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg          if ( ras.state != Unknown_State   &&
1605a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner               End_Profile( RAS_VAR ) )
1606a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1607a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1608a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( New_Profile( RAS_VARS state_bez ) )
1609a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* compute intersections */
16139ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1622a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x4;
1626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y4;
1627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1631a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1632a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  SWAP_
1636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SWAP_( x, y )  do                \
1637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       {                 \
1638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         Long  swap = x; \
1639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         x = y;          \
1642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         y = swap;       \
1643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       } while ( 0 )
1644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Decompose_Curve                                                    */
1650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1652174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Scan the outline arrays in order to emit individual segments and   */
1653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
1654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    weird cases, like when the first point is off the curve, or when   */
1655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    there are simply no `on' points in the contour!                    */
1656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    first   :: The index of the first point in the contour.            */
1659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    last    :: The index of the last point in the contour.             */
1661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the curve.                */
1663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on error.                              */
1666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
166752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
166852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Decompose_Curve( RAS_ARGS UShort  first,
166952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                            UShort  last,
167052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                            int     flipped )
1671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_last;
1673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_control;
1674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_start;
1675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  points;
1677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  point;
1678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  limit;
1679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    char*       tags;
1680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
16818edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    unsigned    tag;       /* current point's state           */
1682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    points = ras.outline.points;
1685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    limit  = points + last;
1686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.x = SCALED( points[first].x );
1688a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.y = SCALED( points[first].y );
1689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.x  = SCALED( points[last].x );
1690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.y  = SCALED( points[last].y );
1691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( flipped )
1693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_start.x, v_start.y );
1695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_last.x, v_last.y );
1696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_control = v_start;
1699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1700a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    point = points + first;
1701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    tags  = ras.outline.tags  + first;
1702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    tag   = FT_CURVE_TAG( tags[0] );
1703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* A contour cannot start with a cubic control point! */
1705b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CUBIC )
1706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Invalid_Outline;
1707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* check first point to determine origin */
1709b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CONIC )
1710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first point is conic control.  Yes, this happens. */
1712b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1714a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at last point if it is on the curve */
1715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start = v_last;
1716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        limit--;
1717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* if both first and last points are conic,         */
1721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at their middle and record its position    */
1722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* for closure                                      */
1723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.x = ( v_start.x + v_last.x ) / 2;
1724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.y = ( v_start.y + v_last.y ) / 2;
1725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_last = v_start;
1727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point--;
1729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags--;
1730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = v_start.x;
1733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = v_start.y;
1734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( point < limit )
1736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point++;
1738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags++;
1739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tag = FT_CURVE_TAG( tags[0] );
1741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      switch ( tag )
1743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1744b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_ON:  /* emit a single line_to */
1745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x, y;
1747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point->x );
1750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point->y );
1751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Line_To( RAS_VARS x, y ) )
1755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          continue;
1757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1759b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
1760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.x = SCALED( point[0].x );
1761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.y = SCALED( point[0].y );
1762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1763a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( flipped )
1764a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          SWAP_( v_control.x, v_control.y );
1765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Do_Conic:
1767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( point < limit )
1768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          FT_Vector  v_middle;
1770a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long       x, y;
1771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point++;
1774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags++;
1775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tag = FT_CURVE_TAG( tags[0] );
1776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point[0].x );
1778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point[0].y );
1779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1780a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1783b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag == FT_CURVE_TAG_ON )
1784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1790b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag != FT_CURVE_TAG_CONIC )
1791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.x = ( v_control.x + x ) / 2;
1794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.y = ( v_control.y + y ) / 2;
1795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                  v_middle.x,  v_middle.y ) )
1798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1799a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1800a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.x = x;
1801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.y = y;
1802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Do_Conic;
1804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                v_start.x,   v_start.y ) )
1808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Fail;
1809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        goto Close;
1811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1812b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      default:  /* FT_CURVE_TAG_CUBIC */
1813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x1, y1, x2, y2, x3, y3;
1815a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point + 1 > limit                             ||
1818b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner               FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point += 2;
1822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags  += 2;
1823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = SCALED( point[-2].x );
1825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y1 = SCALED( point[-2].y );
1826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = SCALED( point[-1].x );
1827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y2 = SCALED( point[-1].y );
1828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x3 = SCALED( point[ 0].x );
1829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y3 = SCALED( point[ 0].y );
1830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x1, y1 );
1834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x2, y2 );
1835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x3, y3 );
1836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point <= limit )
1839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Close;
1848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* close the contour with a line segment */
1853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fail;
1855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Close:
1857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Invalid_Outline:
1860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.error = Raster_Err_Invalid;
1861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Convert_Glyph                                                      */
1871a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1873174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Convert a glyph into a series of segments and arcs and make a      */
1874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    profiles list with them.                                           */
1875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of curve.                    */
1878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE if any error was encountered during    */
1881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    rendering.                                                         */
1882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
188352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
188452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Convert_Glyph( RAS_ARGS int  flipped )
1885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
18868edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    int       i;
18878edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    unsigned  start;
1888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  lastProfile;
1890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fProfile = NULL;
1893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint    = FALSE;
1894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh    = FALSE;
1895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
1897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.numTurns = 0;
1899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile         = (PProfile)ras.top;
1901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->offset = ras.top;
1902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.num_Profs        = 0;
1903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start = 0;
1905a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    for ( i = 0; i < ras.outline.n_contours; i++ )
1907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
19089ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg      ras.state    = Unknown_State;
1909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = NULL;
1910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
19118eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      if ( Decompose_Curve( RAS_VARS (unsigned short)start,
19128eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg                            ras.outline.contours[i],
19138eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg                            flipped ) )
1914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      start = ras.outline.contours[i] + 1;
1917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* We must now see whether the extreme arcs join or not */
1919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( FRAC( ras.lastY ) == 0 &&
1920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY >= ras.minY  &&
1921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY <= ras.maxY  )
1922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
1923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.top--;
1924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* Note that ras.gProfile can be nil if the contour was too small */
1925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* to be drawn.                                                   */
1926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      lastProfile = ras.cProfile;
1928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( End_Profile( RAS_VAR ) )
1929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* close the `next profile in contour' linked list */
1932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.gProfile )
1933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        lastProfile->next = ras.gProfile;
1934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Finalize_Profile_Table( RAS_VAR ) )
1937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
19398edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
1940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
1946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
1947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
1948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Init_Linked                                                          */
1955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Initializes an empty linked list.                                  */
1957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
195852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
195952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Init_Linked( TProfileList*  l )
1960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *l = NULL;
1962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  InsNew                                                               */
1968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Inserts a new profile in a linked list.                            */
1970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
197152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
197252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  InsNew( PProfileList  list,
197352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
1974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
1976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long       x;
1977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
1980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
1981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    x       = profile->X;
1982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
1984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( x < current->X )
1986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        break;
1987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
1988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
1989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    profile->link = current;
1992a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *old          = profile;
1993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  DelOld                                                               */
1999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Removes an old profile from a linked list.                         */
2001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
200252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
200352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  DelOld( PProfileList  list,
200452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
2005a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
2007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
2013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current == profile )
2015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old = current->link;
2017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
2021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
2022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* we should never get there, unless the profile was not part of */
2025a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* the list.                                                     */
2026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Sort                                                                 */
2032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
2034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
2035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    and simple.                                                        */
2036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
203752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
203852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Sort( PProfileList  list )
2039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current, next;
2041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, set the new X coordinate of each profile */
2044ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    current = *list;
2045ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    while ( current )
2046ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    {
2047ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->X       = *current->offset;
2048ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->offset += current->flow;
2049ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->height--;
2050ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current = current->link;
2051ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    }
2052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then sort them */
2054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !current )
2058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return;
2059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    next = current->link;
2061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( next )
2063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current->X <= next->X )
2065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = &current->link;
2067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( !current )
2070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return;
2071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2073a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old          = next;
2075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current->link = next->link;
2076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        next->link    = current;
2077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = list;
2079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2081a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2082a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      next = current->link;
2083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2088a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Vertical Sweep Procedure Set                                         */
2090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the vertical black/white sweep   */
2092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  phase by the generic Draw_Sweep() function.                          */
2093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
209652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
209752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Init( RAS_ARGS Short*  min,
209852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max )
2099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  pitch = ras.target.pitch;
2101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceIncr = (Short)-pitch;
2106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs  = -*min * pitch;
2107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( pitch > 0 )
2108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
2109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_min_x = 0;
2111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_max_x = 0;
2112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
211552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
211652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Span( RAS_ARGS Short       y,
211752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
211852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
211952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
212052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
21238edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    int    c1, c2;
2124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1, f2;
2125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte*  target;
2126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( y );
2128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e1 = TRUNC( CEILING( x1 ) );
2135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
2137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = e1;
2138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
2139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = TRUNC( FLOOR( x2 ) );
2140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 >= 0 && e1 < ras.bWidth )
2142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 < 0 )
2144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = 0;
2145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e2 >= ras.bWidth )
2146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e2 = ras.bWidth - 1;
2147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 = (Short)( e2 >> 3 );
2150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
21518edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
21528edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
21545df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_min_x > c1 )
21555df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_min_x = (short)c1;
21565df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_max_x < c2 )
21575df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_max_x = (short)c2;
2158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      target = ras.bTarget + ras.traceOfs + c1;
2160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 -= c1;
2161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( c2 > 0 )
2163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[0] |= f1;
2165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
216694ffae5239631a18b8b5a39674c0afa8a992410eWerner Lemberg        /* memset() is slower than the following code on many platforms. */
2167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* This is due to the fact that, in the vast majority of cases,  */
2168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the span length in bytes is relatively small.                 */
2169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        c2--;
2170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( c2 > 0 )
2171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *(++target) = 0xFF;
2173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2--;
2174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[1] |= f2;
2176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *target |= ( f1 & f2 );
2179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
218352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
218452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Drop( RAS_ARGS Short       y,
218552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
218652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
218752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
218852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
21905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  c1, f1;
2192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
21965df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   e2            x2                    x1           e1   */
21975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
21985df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 ^                     |                 */
21995df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
22005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   +-------------+---------------------+------------+    */
22015df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
22025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     v                 */
22035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
22045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* pixel         contour              contour       pixel  */
22055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* center                                           center */
22065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
22075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* drop-out mode    scan conversion rules (as defined in OpenType) */
22085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* --------------------------------------------------------------- */
22095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  0                1, 2, 3                                       */
22105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  1                1, 2, 4                                       */
22115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  2                1, 2                                          */
22125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  3                same as mode 2                                */
22135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  4                1, 2, 5                                       */
22145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  5                1, 2, 6                                       */
22155df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  6, 7             same as mode 2                                */
22165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
22175df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
22185df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
22195df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        switch ( ras.dropOutControl )
2226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
22275df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
22285df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2230a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
22325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
2233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22355df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
22365df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
2237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22385df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* Drop-out Control Rules #4 and #6 */
22395df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
22405df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* The spec is not very clear regarding those rules.  It  */
2241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* presents a method that is way too costly to implement  */
2242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* while the general idea seems to get rid of `stubs'.    */
2243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* Here, we only get rid of stubs recognized if:          */
2245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  upper stub:                                           */
2247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Right is the successor of P_Left in that contour */
2250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the top of P_Left and P_Right                 */
2251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  lower stub:                                           */
2253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left is the successor of P_Right in that contour */
2256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the bottom of P_Left                          */
2257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* FIXXXME: uncommenting this line solves the disappearing */
2260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*          bit problem in the `7' of verdana 10pts, but   */
2261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*          makes a new one in the `C' of arial 14pts      */
2262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#if 0
2263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( x2 - x1 < ras.precision_half )
2264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
2265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            /* upper stub test */
2267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( left->next == right && left->height <= 0 )
2268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              return;
2269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            /* lower stub test */
2271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( right->next == left && left->start == y )
2272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              return;
2273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22755df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          if ( ras.dropOutControl == 1 )
22765df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
22775df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
22785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
22795df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22815df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
22825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
22835df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
22865df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = pxl == e1 ? e2 : e1;
2287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        c1 = (Short)( e1 >> 3 );
22915df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1 = (Short)( e1 &  7 );
2292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22935df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( e1 >= 0 && e1 < ras.bWidth                      &&
22945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
22955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;
2296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23015df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 && e1 < ras.bWidth )
2304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2306914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( e1 & 7 );
2307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_min_x > c1 )
23095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_min_x = c1;
23105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_max_x < c1 )
23115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_max_x = c1;
2312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
231852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
231952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Step( RAS_ARG )
2320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs += ras.traceIncr;
2322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2323a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Horizontal Sweep Procedure Set                                     */
2328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the horizontal black/white     */
2330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  sweep phase by the generic Draw_Sweep() function.                  */
2331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
233452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
233552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
233652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  Short*  max )
2337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2338a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing, really */
2339f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( min );
2341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
234552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
234652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Span( RAS_ARGS Short       y,
234752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
234852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
234952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
235052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
2353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  bits;
2354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1;
2355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( x2 - x1 < ras.precision )
2361a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e1 = CEILING( x1 );
2363a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = FLOOR  ( x2 );
2364a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
2366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        bits = ras.bTarget + ( y >> 3 );
2368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        f1   = (Byte)( 0x80 >> ( y & 7 ) );
2369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = TRUNC( e1 );
2371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( e1 >= 0 && e1 < ras.target.rows )
2373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          PByte  p;
2375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p = bits - e1*ras.target.pitch;
2378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( ras.target.pitch > 0 )
2379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            p += ( ras.target.rows - 1 ) * ras.target.pitch;
2380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p[0] |= f1;
2382a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
238852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
238952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
239052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
239152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
239252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
239352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
23955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2396a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  bits;
2397a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1;
2398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2399a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* During the horizontal sweep, we only take care of drop-outs */
2401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e1     +       <-- pixel center */
24035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
24045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x1  ---+-->    <-- contour      */
24055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
24065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
24075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x2  <--+---    <-- contour      */
24085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
24095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
24105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e2     +       <-- pixel center */
24115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
24125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
24135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
24145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2415a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        switch ( ras.dropOutControl )
2421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
24225df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
24235df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24265df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
24275df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
2428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24305df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
24315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
24325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* see Vertical_Sweep_Drop for details */
2433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* rightmost stub test */
2435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( left->next == right && left->height <= 0 )
2436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* leftmost stub test */
2439a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( right->next == left && left->start == y )
2440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24425df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          if ( ras.dropOutControl == 1 )
24435df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
24445df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
24455df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
24465df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24485df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
24495df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
24505df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24525df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
24535df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = pxl == e1 ? e2 : e1;
2454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24555df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2456a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24575df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits = ras.bTarget + ( y >> 3 );
24585df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1   = (Byte)( 0x80 >> ( y & 7 ) );
2459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24605df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits -= e1 * ras.target.pitch;
24615df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( ras.target.pitch > 0 )
24625df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24645df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( e1 >= 0              &&
24655df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             e1 < ras.target.rows &&
24665df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             *bits & f1           )
24675df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;
2468a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2470a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2471a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    bits = ras.bTarget + ( y >> 3 );
2474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    f1   = (Byte)( 0x80 >> ( y & 7 ) );
2475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24765df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 && e1 < ras.target.rows )
2479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits -= e1 * ras.target.pitch;
2481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.target.pitch > 0 )
2482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits[0] |= f1;
2485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
248952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
249052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Step( RAS_ARG )
2491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Nothing, really */
2493f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
2498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Vertical Gray Sweep Procedure Set                                    */
2503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These two routines are used during the vertical gray-levels sweep    */
2505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  phase by the generic Draw_Sweep() function.                          */
2506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  NOTES                                                                */
2508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  - The target pixmap's width *must* be a multiple of 4.               */
2510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2511a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
2512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    span call.                                                         */
2513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
251652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
251752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
251852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                     Short*  max )
2519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  pitch, byte_len;
2521a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2523a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *min = *min & -2;
2524a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *max = ( *max + 3 ) & -2;
2525a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2526a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs  = 0;
2527a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    pitch         = ras.target.pitch;
2528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    byte_len      = -pitch;
2529a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceIncr = (Short)byte_len;
2530a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceG    = ( *min / 2 ) * byte_len;
2531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( pitch > 0 )
2533a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2534a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceG += ( ras.target.rows - 1 ) * pitch;
2535a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      byte_len    = -byte_len;
2536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_min_x =  (Short)byte_len;
2539a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_max_x = -(Short)byte_len;
2540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
254352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
254452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Gray_Sweep_Step( RAS_ARG )
2545a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2546a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int    c1, c2;
2547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  pix, bit, bit2;
254838d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner    char*  count = (char*)count_table;
2549a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte*  grays;
2550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs += ras.gray_width;
2553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2554a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.traceOfs > ras.gray_width )
2555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2556a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
2557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      grays = ras.grays;
2558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.gray_max_x >= 0 )
2560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2561174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Long  last_pixel = ras.target.width - 1;
2562174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Int   last_cell  = last_pixel >> 2;
2563174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Int   last_bit   = last_pixel & 3;
2564174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Bool  over       = 0;
2565a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2566a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2567a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
2568a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2569a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.gray_max_x = last_cell - 1;
2570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          over = 1;
2571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.gray_min_x < 0 )
2574a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.gray_min_x = 0;
2575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2576174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        bit  = ras.bTarget + ras.gray_min_x;
2577174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        bit2 = bit + ras.gray_width;
2578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2579a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        c1 = ras.gray_max_x - ras.gray_min_x;
2580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( c1 >= 0 )
2582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2 = count[*bit] + count[*bit2];
2584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2585a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( c2 )
2586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2587a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[0] = grays[(c2 >> 12) & 0x000F];
2588a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[1] = grays[(c2 >> 8 ) & 0x000F];
2589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[2] = grays[(c2 >> 4 ) & 0x000F];
2590a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[3] = grays[ c2        & 0x000F];
2591a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2592a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit  = 0;
2593a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit2 = 0;
2594a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2595a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2596a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          bit++;
2597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          bit2++;
2598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pix += 4;
2599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c1--;
2600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( over )
2603a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2604a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2 = count[*bit] + count[*bit2];
2605a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( c2 )
2606a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2607a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            switch ( last_bit )
2608a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            {
2609a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            case 2:
2610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[2] = grays[(c2 >> 4 ) & 0x000F];
2611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            case 1:
2612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[1] = grays[(c2 >> 8 ) & 0x000F];
2613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            default:
2614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[0] = grays[(c2 >> 12) & 0x000F];
2615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            }
2616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit  = 0;
2618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit2 = 0;
2619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2622a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceOfs = 0;
2624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceG  += ras.traceIncr;
2625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gray_min_x =  32000;
2627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gray_max_x = -32000;
2628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2631a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
263252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
263352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
263452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x1,
263552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x2,
263652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    left,
263752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    right )
2638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing, really */
2640f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( y );
2642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( x1 );
2643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( x2 );
2644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
264952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
265052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
265152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x1,
265252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x2,
265352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    left,
265452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    right )
2655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
2657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  pixel;
2658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   color;
2659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* During the horizontal sweep, we only take care of drop-outs */
26625df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
2663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e1 = CEILING( x1 );
2664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e2 = FLOOR  ( x2 );
2665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        switch ( ras.dropOutControl )
2671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
26725df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
2673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e1 = e2;
2674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26765df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
26775df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          e1 = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
2678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26805df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
26815df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
26825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* see Vertical_Sweep_Drop for details */
2683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* rightmost stub test */
2685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( left->next == right && left->height <= 0 )
2686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2688a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* leftmost stub test */
2689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( right->next == left && left->start == y )
2690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          if ( ras.dropOutControl == 1 )
2693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            e1 = e2;
2694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          else
26955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            e1 = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
2696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26995df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
27005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
2701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 )
2708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( x2 - x1 >= ras.precision_half )
2710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        color = ras.grays[2];
2711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        color = ras.grays[1];
2713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2714a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e1 = TRUNC( e1 ) / 2;
2715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 < ras.target.rows )
2716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
2718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.target.pitch > 0 )
2719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
2720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( pixel[0] == ras.grays[0] )
2722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pixel[0] = color;
2723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
2729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Generic Sweep Drawing routine                                        */
2734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
273752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
273852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Draw_Sweep( RAS_ARG )
2739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         y, y_change, y_height;
2741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile      P, Q, P_Left, P_Right;
2743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         min_Y, max_Y, top, bottom, dropouts;
2745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long          x1, x2, xs, e1, e2;
2747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27483c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    TProfileList  waiting;
2749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TProfileList  draw_left, draw_right;
2750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2752174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* initialize empty linked lists */
2753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27543c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    Init_Linked( &waiting );
2755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_left  );
2757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_right );
2758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* first, compute min and max Y */
2760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P     = ras.fProfile;
2762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    max_Y = (Short)TRUNC( ras.minY );
2763a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    min_Y = (Short)TRUNC( ras.maxY );
2764a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Q = P->link;
2768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bottom = (Short)P->start;
2770914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      top    = (Short)( P->start + P->height - 1 );
2771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27725df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( min_Y > bottom )
27735df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        min_Y = bottom;
27745df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( max_Y < top )
27755df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        max_Y = top;
2776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P->X = 0;
27783c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      InsNew( &waiting, P );
2779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2780a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = Q;
2781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2783174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* check the Y-turns */
2784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.numTurns == 0 )
2785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Invalid;
2787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
2788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2790174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* now initialize the sweep */
2791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2794174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* then compute the distance of each profile from min_Y */
2795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27963c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    P = waiting;
2797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2799a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2800914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      P->countL = (UShort)( P->start - min_Y );
2801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = P->link;
2802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2804174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* let's go */
2805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y        = min_Y;
2807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_height = 0;
2808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.numTurns > 0 &&
2810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner         ras.sizeBuff[-ras.numTurns] == min_Y )
2811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns--;
2812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.numTurns > 0 )
2814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2815174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* check waiting list for new activations */
2816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28173c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      P = waiting;
2818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P->countL -= y_height;
2823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->countL == 0 )
2824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
28253c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg          DelOld( &waiting, P );
2826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          switch ( P->flow )
2828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          case Flow_Up:
2830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_left,  P );
2831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            break;
2832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          case Flow_Down:
2834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_right, P );
2835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            break;
2836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2842174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* sort the drawing lists */
2843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_left );
2845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_right );
2846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
28488eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      y_height = (Short)( y_change - y );
2849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( y < y_change )
2851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2852174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* let's trace */
2853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts = 0;
2855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left  = draw_left;
2857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Right = draw_right;
2858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( P_Left )
2860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = P_Left ->X;
2862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = P_Right->X;
2863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( x1 > x2 )
2865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            xs = x1;
2867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x1 = x2;
2868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x2 = xs;
2869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
287171b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e1 = FLOOR( x1 );
287271b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e2 = CEILING( x2 );
2873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
287471b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          if ( x2 - x1 <= ras.precision &&
287571b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg               e1 != x1 && e2 != x2     )
287671b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          {
2877ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg            if ( e1 > e2 || e2 == e1 + ras.precision )
2878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            {
2879ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              if ( ras.dropOutControl != 2 )
2880ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              {
2881174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                /* a drop-out was detected */
2882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2883ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left ->X = x1;
2884ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Right->X = x2;
2885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2886ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                /* mark profile for drop-out processing */
2887ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left->countL = 1;
2888ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                dropouts++;
2889ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              }
2890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Skip_To_Next;
2892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            }
2893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
2896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Skip_To_Next:
2898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Left  = P_Left->link;
2900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Right = P_Right->link;
2901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2903174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* handle drop-outs _after_ the span drawing --       */
2904174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* drop-out processing has been moved out of the loop */
2905174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* for performance tuning                             */
2906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( dropouts > 0 )
2907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Scan_DropOuts;
2908a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Next_Line:
2910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Step( RAS_VAR );
2912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y++;
2914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < y_change )
2916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_left  );
2918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_right );
2919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2922174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* now finalize the profiles that need it */
2923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_left;
2925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
2929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_left, P );
2930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_right;
2934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
2938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_right, P );
2939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2943174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* for gray-scaling, flush the bitmap scanline cache */
2944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( y <= max_Y )
2945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step( RAS_VAR );
2947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y++;
2948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
2951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Scan_DropOuts:
2953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Left  = draw_left;
2955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Right = draw_right;
2956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P_Left )
2958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( P_Left->countL )
2960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left->countL = 0;
2962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#if 0
2963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts--;  /* -- this is useful when debugging only */
2964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
2965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Drop( RAS_VARS y,
2966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left->X,
2967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right->X,
2968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left,
2969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right );
2970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Left  = P_Left->link;
2973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Right = P_Right->link;
2974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    goto Next_Line;
2977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
2983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Single_Pass                                                 */
2984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
2986174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Perform one sweep with sub-banding.                                */
2987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
2989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the outline.              */
2990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
2992a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Renderer error code.                                               */
2993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
299452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
299552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Single_Pass( RAS_ARGS Bool  flipped )
2996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  i, j, k;
2998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.band_top >= 0 )
3001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
3003a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
3004a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3005a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top = ras.buff;
3006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_None;
3008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Convert_Glyph( RAS_VARS flipped ) )
3010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.error != Raster_Err_Overflow )
3012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
3013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.error = Raster_Err_None;
3015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* sub-banding */
3017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef DEBUG_RASTER
3019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
3020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        i = ras.band_stack[ras.band_top].y_min;
3023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        j = ras.band_stack[ras.band_top].y_max;
3024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
30258eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        k = (Short)( ( i + j ) / 2 );
3026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.band_top >= 7 || k < i )
3028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
3029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.band_top = 0;
3030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.error    = Raster_Err_Invalid;
3031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return ras.error;
3033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
3034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_min = k;
3036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_max = j;
3037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
30388eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
3039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top++;
3041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
3043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.fProfile )
3045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Draw_Sweep( RAS_VAR ) )
3046a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner             return ras.error;
3047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top--;
3048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
3052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
3056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
3058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Glyph                                                       */
3059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
3061174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Render a glyph in a bitmap.  Sub-banding if needed.                */
3062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
3064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    FreeType error code.  0 means success.                             */
3065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3066bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
306752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Glyph( RAS_ARG )
3068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
3070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Set_High_Precision( RAS_VARS ras.outline.flags &
3073b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner                        FT_OUTLINE_HIGH_PRECISION );
30745df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.scale_shift = ras.precision_shift;
30755df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
30765df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
30775df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      ras.dropOutControl = 2;
30785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    else
30795df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    {
30805df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
30815df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 4;
30825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      else
30835df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 0;
30845df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
30855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
30865df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl += 1;
30875df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    }
30885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
30895df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.second_pass = (FT_Byte)( !( ras.outline.flags &
30905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg                                    FT_OUTLINE_SINGLE_PASS ) );
3091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Vertical Sweep */
3093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
3094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
3097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_top            = 0;
3099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_min = 0;
31008eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
3101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31028edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    ras.bWidth  = (unsigned short)ras.target.width;
3103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bTarget = (Byte*)ras.target.buffer;
3104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
3106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return error;
3107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Horizontal Sweep */
3109ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg    if ( ras.second_pass && ras.dropOutControl != 2 )
3110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_top            = 0;
3117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_min = 0;
31188eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
3119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return error;
3122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3124f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_None;
3125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
3129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
3131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
3133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Gray_Glyph                                                  */
3134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
3136174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Render a glyph with grayscaling.  Sub-banding if needed.           */
3137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
3139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    FreeType error code.  0 means success.                             */
3140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3141bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
314252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Gray_Glyph( RAS_ARG )
3143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      pixel_width;
3145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
3146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Set_High_Precision( RAS_VARS ras.outline.flags &
3149b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner                        FT_OUTLINE_HIGH_PRECISION );
31505df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.scale_shift = ras.precision_shift + 1;
31515df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
31525df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
31535df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      ras.dropOutControl = 2;
31545df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    else
31555df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    {
31565df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
31575df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 4;
31585df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      else
31595df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 0;
31605df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
31615df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
31625df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl += 1;
31635df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    }
31645df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
31655df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
3166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Vertical Sweep */
3168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_top            = 0;
3170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_min = 0;
3171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
3172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bWidth  = ras.gray_width;
3174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
3175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.bWidth > pixel_width )
3177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.bWidth = pixel_width;
3178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bWidth  = ras.bWidth * 8;
3180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bTarget = (Byte*)ras.gray_lines;
3181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gTarget = (Byte*)ras.target.buffer;
3182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
3184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
3187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    error = Render_Single_Pass( RAS_VARS 0 );
3189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( error )
3190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return error;
3191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Horizontal Sweep */
3193ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg    if ( ras.second_pass && ras.dropOutControl != 2 )
3194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
3197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
3198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_top            = 0;
3201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_min = 0;
3202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
3203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      error = Render_Single_Pass( RAS_VARS 1 );
3205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( error )
3206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return error;
3207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3209f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_None;
3210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3212bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
3213a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3214bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
3215bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  Render_Gray_Glyph( RAS_ARG )
3216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED_RASTER;
3218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3219f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_Unsupported;
3220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3222bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
3223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
322552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
32268a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_init( PRaster  raster )
3227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
322938d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner    FT_UInt  n;
3230a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
32314ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg
3232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* set default 5-levels gray palette */
3233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    for ( n = 0; n < 5; n++ )
3234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      raster->grays[n] = n * 255 / 4;
3235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
32368a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    raster->gray_width = RASTER_GRAY_LINES / 2;
3237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3238eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg#else
3239eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg    FT_UNUSED( raster );
3240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /****                         a static object.                  *****/
3246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef _STANDALONE_
3249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
325152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
3252174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_new( void*       memory,
325352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                FT_Raster  *araster )
3254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
32558a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner     static TRaster  the_raster;
3256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3258f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg     *araster = (FT_Raster)&the_raster;
3259b3d5e9cf03dce78e606b79c81cb1f29ce06555d5Werner Lemberg     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
3260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     ft_black_init( &the_raster );
3261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     return 0;
3263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
326652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
326752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  ft_black_done( FT_Raster  raster )
3268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing */
3270f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED( raster );
3271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else /* _STANDALONE_ */
3275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
327752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
32788a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_new( FT_Memory   memory,
32798a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner                PRaster    *araster )
3280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
32818a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    FT_Error  error;
32828a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    PRaster   raster;
3283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *araster = 0;
3286e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    if ( !FT_NEW( raster ) )
3287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      raster->memory = memory;
3289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ft_black_init( raster );
3290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *araster = raster;
3292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return error;
3295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
329852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
32998a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_done( PRaster  raster )
3300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Memory  memory = (FT_Memory)raster->memory;
3302e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    FT_FREE( raster );
3303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* _STANDALONE_ */
3307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
330952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
3310174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_reset( PRaster  raster,
3311174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                  char*    pool_base,
3312174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                  long     pool_size )
3313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
33148a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    if ( raster )
3315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
33168a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )
33178a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      {
33188a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        PWorker  worker = (PWorker)pool_base;
33198a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
33204ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg
33214ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg        raster->buffer      = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );
33224ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg        raster->buffer_size = ( ( pool_base + pool_size ) -
33234ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg                                (char*)raster->buffer ) / sizeof ( Long );
33248a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->worker      = worker;
33258a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      }
33268a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      else
33278a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      {
33288a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->buffer      = NULL;
33298a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->buffer_size = 0;
33308a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->worker      = NULL;
33318a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      }
3332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
333652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
3337174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_set_mode( PRaster        raster,
3338174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                     unsigned long  mode,
3339174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                     const char*    palette )
3340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
3342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
3344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* set 5-levels gray palette */
33468a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[0] = palette[0];
33478a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[1] = palette[1];
33488a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[2] = palette[2];
33498a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[3] = palette[3];
33508a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[4] = palette[4];
3351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else
3354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( raster );
3356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( mode );
3357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( palette );
3358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3361a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
336352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
33648a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_render( PRaster                  raster,
3365fa420250c59414e432243feffb70be68654b8c27Werner Lemberg                   const FT_Raster_Params*  params )
3366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
33678ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Outline*  outline    = (const FT_Outline*)params->source;
33688ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Bitmap*   target_map = params->target;
33698a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    PWorker            worker;
3370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33728a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    if ( !raster || !raster->buffer || !raster->buffer_size )
3373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Not_Ini;
3374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33751ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline )
33761ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg      return Raster_Err_Invalid;
33771ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg
3378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* return immediately if the outline is empty */
3379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( outline->n_points == 0 || outline->n_contours <= 0 )
3380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_None;
3381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33821ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline->contours || !outline->points )
3383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Invalid;
3384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3385c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( outline->n_points !=
3386c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg           outline->contours[outline->n_contours - 1] + 1 )
3387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Invalid;
3388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33898a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    worker = raster->worker;
33908a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
3391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* this version of the raster does not support direct rendering, sorry */
3392b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( params->flags & FT_RASTER_FLAG_DIRECT )
3393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Unsupported;
3394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3395c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map )
3396c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg      return Raster_Err_Invalid;
3397c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3398c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    /* nothing to do */
3399c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->width || !target_map->rows )
3400c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg      return Raster_Err_None;
3401c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3402c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->buffer )
34031eb9a43aa14e02b56d981bae334e6e24c63298f7David Turner      return Raster_Err_Invalid;
34041eb9a43aa14e02b56d981bae334e6e24c63298f7David Turner
34055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.outline = *outline;
34065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.target  = *target_map;
3407a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
34085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->buff       = (PLong) raster->buffer;
34095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->sizeBuff   = worker->buff +
34105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg                           raster->buffer_size / sizeof ( Long );
34118a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
34125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->grays      = raster->grays;
34135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->gray_width = raster->gray_width;
34148a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#endif
34158a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
3416b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    return ( ( params->flags & FT_RASTER_FLAG_AA )
3417f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg               ? Render_Gray_Glyph( RAS_VAR )
3418f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg               : Render_Glyph( RAS_VAR ) );
3419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3422a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  const FT_Raster_Funcs  ft_standard_raster =
3423a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3424b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    FT_GLYPH_FORMAT_OUTLINE,
3425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_New_Func)     ft_black_new,
3426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Reset_Func)   ft_black_reset,
3427a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
3428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Render_Func)  ft_black_render,
3429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Done_Func)    ft_black_done
3430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  };
3431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/* END */
3434