ftraster.c revision 766b822f4c1cc84cc11545b63be87108d0954b48
1a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/***************************************************************************/
2a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
3a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  ftraster.c                                                             */
4a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
5a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*    The FreeType glyph rasterizer (body).                                */
6a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
7b66efefdcde552e4880896aa961a0b9a583762d2Werner Lemberg/*  Copyright 1996-2001, 2002, 2003, 2005, 2007, 2008, 2009 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
520d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define FT_CONFIG_STANDARD_LIBRARY_H  <stdlib.h>
530d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
54766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg#include <string.h>           /* for memset */
550d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
56f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftmisc.h"
57f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftimage.h"
58f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
59f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#else /* !_STANDALONE_ */
60a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
6119ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include <ft2build.h>
628d3a401fa808a8c70bd6a9ce17d5a840fb0ae2dbDavid Turner#include "ftraster.h"
6319ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
64a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
650d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#include "rastpic.h"
660d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
67f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif /* !_STANDALONE_ */
68f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
69a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
70a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
71a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
72a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A simple technical note on how the raster works                       */
73a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* -----------------------------------------------                       */
74a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
75a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Converting an outline into a bitmap is achieved in several steps:   */
76a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
77a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
78a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       profile is simply an array of scanline intersections on a given */
79a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       dimension.  A profile's main attributes are                     */
80a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
818262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'      */
82a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
83a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o an array of intersection coordinates for each scanline        */
848262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*         between `Ymin' and `Ymax'                                     */
85a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
86a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o a direction, indicating whether it was built going `up' or    */
878262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*         `down', as this is very important for filling rules           */
888262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*                                                                       */
898262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*       o its drop-out mode                                             */
90a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
91a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   2 - Sweeping the target map's scanlines in order to compute segment */
92a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       `spans' which are then filled.  Additionally, this pass         */
93a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       performs drop-out control.                                      */
94a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
95a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The outline data is parsed during step 1 only.  The profiles are    */
96a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the bottom of the render pool, used as a stack.  The     */
97a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   following graphics shows the profile list under construction:       */
98a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
998262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*     __________________________________________________________ _ _    */
1008262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |         |                 |         |                 |          */
1018262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    | profile | coordinates for | profile | coordinates for |-->       */
1028262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |    1    |  profile 1      |    2    |  profile 2      |-->       */
1038262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |_________|_________________|_________|_________________|__ _ _    */
104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1058262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    ^                                                       ^          */
1068262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |                                                       |          */
1078262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* start of render pool                                      top         */
108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The top of the profile stack is kept in the `top' variable.         */
110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   As you can see, a profile record is pushed on top of the render     */
112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   pool, which is then followed by its coordinates/intersections.  If  */
113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   a change of direction is detected in the outline, a new profile is  */
114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   generated until the end of the outline.                             */
115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Note that when all profiles have been generated, the function       */
117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   bottom-most scanline as well as the scanline above its upmost       */
119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   boundary.  These positions are called `y-turns' because they (sort  */
120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   of) correspond to local extrema.  They are stored in a sorted list  */
121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the top of the render pool as a downwards stack:         */
122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ _______________________________________                      */
124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--| sorted list of     |                     */
126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--|  extrema scanlines |                     */
127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ __________________|____________________|                     */
128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            ^                    ^                     */
130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         maxBuff           sizeBuff = end of pool      */
132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   This list is later used during the sweep phase in order to          */
134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   optimize performance (see technical note on the sweep below).       */
135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Of course, the raster detects whether the two stacks collide and    */
1376e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg  /*   handles the situation properly.                                     */
138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  CONFIGURATION MACROS                                               **/
146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* define DEBUG_RASTER if you want to compile a debugging version */
151766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg/* #define DEBUG_RASTER */
152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
153766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
154766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /* 5-levels anti-aliasing                                       */
155766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg/* #define FT_RASTER_OPTION_ANTI_ALIASING */
156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The size of the two-lines intermediate bitmap used */
158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* for anti-aliasing, in bytes.                       */
159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RASTER_GRAY_LINES  2048
160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  OTHER MACROS (do not change)                                       **/
166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* messages during execution.                                            */
175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  FT_COMPONENT
177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_COMPONENT  trace_raster
178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef _STANDALONE_
181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* This macro is used to indicate that a function parameter is unused. */
184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* ANSI compilers (e.g. LCC).                                          */
187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_UNUSED( x )  (x) = (x)
188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Disable the tracing mechanism for simplicity -- developers can      */
190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* activate it easily by redefining these two macros.                  */
191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_ERROR
192f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_ERROR( x )  do { } while ( 0 )     /* nothing */
193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_TRACE
196f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE( x )   do { } while ( 0 )    /* nothing */
197f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE1( x )  do { } while ( 0 )    /* nothing */
198f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE6( x )  do { } while ( 0 )    /* nothing */
199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_None          0
202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Not_Ini      -1
203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Overflow     -2
204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Neg_Height   -3
205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Invalid      -4
206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Unsupported  -5
207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2080d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define ft_memset  memset
2090d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
2100d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
2110d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg                                raster_reset_, raster_set_mode_,    \
2120d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg                                raster_render_, raster_done_ )      \
2130d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg          const FT_Raster_Funcs class_ =                            \
2140d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg          {                                                         \
2150d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            glyph_format_,                                          \
2160d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_new_,                                            \
2170d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_reset_,                                          \
2180d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_set_mode_,                                       \
2190d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_render_,                                         \
2200d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_done_                                            \
2210d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg         };
2228262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg
2238262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#else /* !_STANDALONE_ */
224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2261f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include FT_INTERNAL_OBJECTS_H
2271f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2291f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include "rasterrs.h"
2301f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg
2311f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_None         Raster_Err_Ok
2321f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
2331f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
2341f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
2351f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
2361f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2398262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#endif /* !_STANDALONE_ */
240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
242e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner#ifndef FT_MEM_SET
243d15bc0d13a163995e1ca11925349bd64d1c33617David Turner#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
244c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg#endif
245c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
246f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifndef FT_MEM_ZERO
247f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
248f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif
249c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* typically a small value and the result of a*b is known to fit into */
252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* 32 bits.                                                           */
253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* defined in `ftcalc.h'.                                                */
258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SMulDiv  FT_MulDiv
259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The rasterizer is a very general purpose component; please leave */
261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* the following redefinitions there (you never know your target    */
262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* environment).                                                    */
263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef TRUE
265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define TRUE   1
266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FALSE
269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FALSE  0
270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef NULL
273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define NULL  (void*)0
274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef SUCCESS
277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SUCCESS  0
278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FAILURE
281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FAILURE  1
282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* Setting this constant to more than 32 is a   */
287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* pure waste of space.                         */
288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SIMPLE TYPE DECLARATIONS                                           **/
296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef int             Int;
301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned int    UInt;
302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef short           Short;
303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned short  UShort, *PUShort;
304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef long            Long, *PLong;
305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned long   ULong;
306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned char   Byte, *PByte;
308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef char            Bool;
309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
310fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
311fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg  typedef union  Alignment_
3128530a228889128adfd446514928f36663ed20f04David Turner  {
3138530a228889128adfd446514928f36663ed20f04David Turner    long    l;
3148530a228889128adfd446514928f36663ed20f04David Turner    void*   p;
3158530a228889128adfd446514928f36663ed20f04David Turner    void  (*f)(void);
3168530a228889128adfd446514928f36663ed20f04David Turner
3178530a228889128adfd446514928f36663ed20f04David Turner  } Alignment, *PAlignment;
3188530a228889128adfd446514928f36663ed20f04David Turner
319fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct  TPoint_
321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  x;
323a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  y;
324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TPoint;
326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
32842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /* values for the `flags' bit field */
32972271140434028186a49a5dc5925f0727559e46fWerner Lemberg#define Flow_Up           0x8
33072271140434028186a49a5dc5925f0727559e46fWerner Lemberg#define Overshoot_Top     0x10
33172271140434028186a49a5dc5925f0727559e46fWerner Lemberg#define Overshoot_Bottom  0x20
332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* States of each line, arc, and profile */
335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef enum  TStates_
336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3379ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Unknown_State,
3389ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Ascending_State,
3399ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Descending_State,
3409ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Flat_State
341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TStates;
343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct TProfile_  TProfile;
346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef TProfile*         PProfile;
347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  struct  TProfile_
349a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
35042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    FT_F26Dot6  X;           /* current coordinate during sweep          */
35142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PProfile    link;        /* link to next profile (various purposes)  */
35242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PLong       offset;      /* start of profile's data in render pool   */
35372271140434028186a49a5dc5925f0727559e46fWerner Lemberg    unsigned    flags;       /* Bit 0-2: drop-out mode                   */
35472271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 3: profile orientation (up/down)     */
35572271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 4: is top profile?                   */
35672271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 5: is bottom profile?                */
35742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    long        height;      /* profile's height in scanlines            */
35842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    long        start;       /* profile's starting scanline              */
35942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
36042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    unsigned    countL;      /* number of lines to step before this      */
36142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             /* profile becomes drawable                 */
36242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
36342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PProfile    next;        /* next profile in same contour, used       */
36442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             /* during drop-out control                  */
365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  };
366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile   TProfileList;
368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile*  PProfileList;
369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Simple record used to implement a stack of bands, required */
372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* by the sub-banding mechanism                               */
373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct  TBand_
374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_min;   /* band's minimum */
376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_max;   /* band's maximum */
377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TBand;
379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define AlignProfileSize \
382fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
385f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARGS       /* void */
389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARG        /* void */
390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VARS       /* void */
392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VAR        /* void */
393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
394f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_UNUSED_RASTER  do { } while ( 0 )
395a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
396a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3978262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#else /* !FT_STATIC_RASTER */
398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
399a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4008a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_ARGS       PWorker    worker,
4018a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_ARG        PWorker    worker
402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4038a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VARS       worker,
4048a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VAR        worker
405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4068a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define FT_UNUSED_RASTER  FT_UNUSED( worker )
407a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4098262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#endif /* !FT_STATIC_RASTER */
410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
411a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
412174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  typedef struct TWorker_  TWorker, *PWorker;
413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
415a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* prototypes used for sweep function dispatch */
41652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
41752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Init( RAS_ARGS Short*  min,
41852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max );
419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
42052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
42152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Span( RAS_ARGS Short       y,
42252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
42352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
42452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
42552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right );
426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
42752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
42852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Step( RAS_ARG );
429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* NOTE: These operations are only valid on 2's complement processors */
432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FLOOR( x )    ( (x) & -ras.precision )
434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
43942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg#define IS_BOTTOM_OVERSHOOT( x )  ( CEILING( x ) - x >= ras.precision_half )
44042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg#define IS_TOP_OVERSHOOT( x )     ( x - FLOOR( x ) >= ras.precision_half )
44142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
4428262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* The most used variables are positioned at the top of the structure. */
4438262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* Thus, their offset can be coded with less opcodes, resulting in a   */
4448262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* smaller executable.                                                 */
445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4468a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  struct  TWorker_
447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
4488262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_bits;     /* precision related variables         */
4498262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision;
4508262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_half;
4518262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        precision_mask;
4528262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_shift;
4538262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_step;
4548262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_jitter;
4558262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg
4568262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         scale_shift;        /* == precision_shift   for bitmaps    */
457a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* == precision_shift+1 for pixmaps    */
458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4598262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       buff;               /* The profiles buffer                 */
4608262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       sizeBuff;           /* Render pool size                    */
4618262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       maxBuff;            /* Profiles buffer size                */
4628262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       top;                /* Current cursor in buffer            */
463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4648262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    FT_Error    error;
465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4668262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         numTurns;           /* number of Y-turns in outline        */
467a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4688262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TPoint*     arc;                /* current Bezier arc pointer          */
469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4708262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    UShort      bWidth;             /* target bitmap width                 */
4718262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PByte       bTarget;            /* target bitmap buffer                */
4728262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PByte       gTarget;            /* target pixmap buffer                */
473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4748262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        lastX, lastY;
4758262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        minY, maxY;
476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4778262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    UShort      num_Profs;          /* current number of profiles          */
478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4798262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        fresh;              /* signals a fresh new profile which   */
48090c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg                                    /* `start' field must be completed     */
4818262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        joint;              /* signals that the last arc ended     */
482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* exactly on a scanline.  Allows      */
483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* removal of doublets                 */
4848262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    cProfile;           /* current profile                     */
4858262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    fProfile;           /* head of linked list of profiles     */
4868262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    gProfile;           /* contour's first profile in case     */
487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* of impact                           */
488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4898262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TStates     state;              /* rendering state                     */
490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Bitmap   target;             /* description of target bit/pixmap    */
492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Outline  outline;
493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4948262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        traceOfs;           /* current offset in target bitmap     */
4958262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        traceG;             /* current offset in target pixmap     */
496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4978262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short       traceIncr;          /* sweep's increment in target bitmap  */
498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4998262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short       gray_min_x;         /* current min x during gray rendering */
5008262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short       gray_max_x;         /* current max x during gray rendering */
501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* dispatch variables */
503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Init*  Proc_Sweep_Init;
505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Span;
506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Drop;
507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Step*  Proc_Sweep_Step;
508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5098262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Byte        dropOutControl;     /* current drop_out control method     */
510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5118262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        second_pass;        /* indicates whether a horizontal pass */
512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* should be performed to control      */
513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* drop-out accurately when calling    */
514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* Render_Glyph.  Note that there is   */
515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* no horizontal pass during gray      */
516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* rendering.                          */
517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5188262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5208262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TBand       band_stack[16];     /* band stack used for sub-banding     */
5218262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         band_top;           /* band stack top                      */
522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
523a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
524a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5258262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Byte*       grays;
526a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5278262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Byte        gray_lines[RASTER_GRAY_LINES];
528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* Intermediate table used to render the   */
529a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* graylevels pixmaps.                     */
530a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* gray_lines is a buffer holding two      */
531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* monochrome scanlines                    */
532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5338262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short       gray_width;     /* width in bytes of one monochrome        */
534a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* intermediate scanline of gray_lines.    */
535a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                /* Each gray pixel takes 2 bits long there */
536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       /* The gray_lines must hold 2 lines, thus with size */
538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       /* in bytes of at least `gray_width*2'.             */
539a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* FT_RASTER_ANTI_ALIASING */
541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5428a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  };
543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
544a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
545174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  typedef struct  TRaster_
5468a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  {
5478262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    char*    buffer;
5488262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    long     buffer_size;
5498262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    void*    memory;
5508262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PWorker  worker;
5518262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Byte     grays[5];
5528262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short    gray_width;
553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5548a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  } TRaster, *PRaster;
555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
556f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
558174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  static TWorker  cur_ras;
559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define ras  cur_ras
560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5618262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#else /* !FT_STATIC_RASTER */
562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5638a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define ras  (*worker)
564a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5658262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#endif /* !FT_STATIC_RASTER */
566a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
567a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
56839c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg#ifdef FT_RASTER_OPTION_ANTI_ALIASING
56939c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg
570766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /* A lookup table used to quickly count set bits in four gray 2x2 */
571766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /* cells.  The values of the table have been produced with the    */
572766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /* following code:                                                */
573766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*                                                                */
574766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*   for ( i = 0; i < 256; i++ )                                  */
575766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*   {                                                            */
576766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     l = 0;                                                     */
577766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     j = i;                                                     */
578766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*                                                                */
579766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     for ( c = 0; c < 4; c++ )                                  */
580766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     {                                                          */
581766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*       l <<= 4;                                                 */
582766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*                                                                */
583766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*       if ( j & 0x80 ) l++;                                     */
584766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*       if ( j & 0x40 ) l++;                                     */
585766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*                                                                */
586766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*       j = ( j << 2 ) & 0xFF;                                   */
587766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     }                                                          */
588766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*     printf( "0x%04X", l );                                     */
589766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*   }                                                            */
590766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  /*                                                                */
591766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg
592766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg  static const short  count_table[256] =
593174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  {
594766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
595766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
596766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
597766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
598766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
599766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
600766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
601766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
602766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
603766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
604766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
605766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
606766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
607766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
608766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
609766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
610766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
611766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
612766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
613766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
614766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
615766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
616766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
617766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
618766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
619766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
620766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
621766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
622766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
623766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
624766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
625766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
626cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg  };
62738d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
62839c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
62939c91ad444ac05cc45b54ff48d2d5b70dde01904Werner Lemberg
63038d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
63138d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner
632a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  PROFILES COMPUTATION                                               **/
636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Set_High_Precision                                                 */
645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
647174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Set precision variables according to param flag.                   */
648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    High :: Set to True for high precision (typically for ppem < 18),  */
651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*            false otherwise.                                           */
652a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
65352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
65452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Set_High_Precision( RAS_ARGS Int  High )
655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( High )
657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
6580409ef32686188c1947298e0fca9fbeadd23c1c3Werner Lemberg      ras.precision_bits   = 12;
6590409ef32686188c1947298e0fca9fbeadd23c1c3Werner Lemberg      ras.precision_step   = 256;
6600409ef32686188c1947298e0fca9fbeadd23c1c3Werner Lemberg      ras.precision_jitter = 50;
661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_bits   = 6;
665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_step   = 32;
666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_jitter = 2;
667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
67168e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg    ras.precision       = 1 << ras.precision_bits;
672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_half  = ras.precision / 2;
673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_shift = ras.precision_bits - Pixel_Bits;
674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_mask  = -ras.precision;
675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New_Profile                                                        */
682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
684174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Create a new profile in the render pool.                           */
685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
68742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    aState    :: The state/orientation of the new profile.             */
68842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                                                                       */
68942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    overshoot :: Whether the profile's unrounded start position        */
69042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                 differs by at least a half pixel.                     */
691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
69652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
69742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  New_Profile( RAS_ARGS TStates  aState,
69842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                        Bool     overshoot )
699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
700a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.fProfile )
701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile  = (PProfile)ras.top;
703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile  = ras.cProfile;
704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top      += AlignProfileSize;
705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
71342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->flags  = 0;
71442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->start  = 0;
71542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->height = 0;
71642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->offset = ras.top;
71742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->link   = (PProfile)0;
71842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->next   = (PProfile)0;
71972271140434028186a49a5dc5925f0727559e46fWerner Lemberg    ras.cProfile->flags  = ras.dropOutControl;
72042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( aState )
722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
7239ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
72490c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg      ras.cProfile->flags |= Flow_Up;
72542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
72642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        ras.cProfile->flags |= Overshoot_Bottom;
72742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
7319ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
73242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
73342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        ras.cProfile->flags |= Overshoot_Top;
734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
738858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "New_Profile: invalid profile direction\n" ));
739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Invalid;
740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.gProfile )
744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = ras.cProfile;
745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.state = aState;
747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh = TRUE;
748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    End_Profile                                                        */
758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
760174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Finalize the current profile.                                      */
761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
76242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /* <Input>                                                               */
76342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    overshoot :: Whether the profile's unrounded end position differs  */
76442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                 by at least a half pixel.                             */
76542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                                                                       */
766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
76952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
77042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  End_Profile( RAS_ARGS Bool  overshoot )
771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      h;
773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  oldProfile;
774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
776914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg    h = (Long)( ras.top - ras.cProfile->offset );
777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h < 0 )
779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
780858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "End_Profile: negative height encountered\n" ));
781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Neg_Height;
782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
783a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h > 0 )
786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                  (long)ras.cProfile, ras.cProfile->start, h ));
789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = h;
79142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
79242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      {
79342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( ras.cProfile->flags & Flow_Up )
79442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          ras.cProfile->flags |= Overshoot_Top;
79542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        else
79642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          ras.cProfile->flags |= Overshoot_Bottom;
79742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      }
798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
79942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      oldProfile   = ras.cProfile;
80042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      ras.cProfile = (PProfile)ras.top;
80142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
80242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      ras.top += AlignProfileSize;
803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = 0;
805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->offset = ras.top;
80642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
80742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      oldProfile->next = ras.cProfile;
808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.num_Profs++;
809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE1(( "overflow in End_Profile\n" ));
814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
815a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Insert_Y_Turn                                                      */
828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
830174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Insert a salient into the sorted list placed on top of the render  */
831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    pool.                                                              */
832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New y scanline position.                                           */
835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
83952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
84052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Insert_Y_Turn( RAS_ARGS Int  y )
841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
84251daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg    PLong  y_turns;
84351daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg    Int    y2, n;
844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n       = ras.numTurns - 1;
847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_turns = ras.sizeBuff - ras.numTurns;
848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* look for first y value that is <= */
850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( n >= 0 && y < y_turns[n] )
851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      n--;
852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* if it is <, simply insert it, ignore if == */
854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n >= 0 && y > y_turns[n] )
855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( n >= 0 )
856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
85768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg        y2 = (Int)y_turns[n];
858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y_turns[n] = y;
859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y = y2;
860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        n--;
861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n < 0 )
864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
86551daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg      ras.maxBuff--;
866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.maxBuff <= ras.top )
867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.error = Raster_Err_Overflow;
869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
871a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns++;
872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.sizeBuff[-ras.numTurns] = y;
873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Finalize_Profile_Table                                             */
883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
885174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Adjust all links in the profiles list.                             */
886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
89052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
89152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Finalize_Profile_Table( RAS_ARG )
892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int       bottom, top;
894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    UShort    n;
895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  p;
896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n = ras.num_Profs;
899b66efefdcde552e4880896aa961a0b9a583762d2Werner Lemberg    p = ras.fProfile;
900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
901b66efefdcde552e4880896aa961a0b9a583762d2Werner Lemberg    if ( n > 1 && p )
902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( n > 0 )
904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
905a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( n > 1 )
906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = (PProfile)( p->offset + p->height );
907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
908a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = NULL;
909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
91090c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        if ( p->flags & Flow_Up )
91190c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        {
91290c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          bottom = (Int)p->start;
91390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          top    = (Int)( p->start + p->height - 1 );
91490c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        }
91590c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        else
916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
91768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          bottom     = (Int)( p->start - p->height + 1 );
91868e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          top        = (Int)p->start;
919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->start   = bottom;
920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->offset += p->height - 1;
921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
92390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
92490c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg             Insert_Y_Turn( RAS_VARS top + 1 ) )
925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        p = p->link;
928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        n--;
929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile = NULL;
933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Conic                                                        */
942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
944174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide one conic Bezier into two joint sub-arcs in the Bezier   */
945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    stack.                                                             */
946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    None (subdivided Bezier is taken from the top of the stack).       */
949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    loop that should be optimized to hell to get the best performance. */
953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
95452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
95552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Conic( TPoint*  base )
956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b;
958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = base[2].x;
961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x;
962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].x = ( base[2].x + b ) / 2;
963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x = ( base[0].x + b ) / 2;
964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = ( a + b ) / 2;
965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = base[2].y;
967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y;
968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].y = ( base[2].y + b ) / 2;
969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y = ( base[0].y + b ) / 2;
970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = ( a + b ) / 2;
971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* hand optimized.  gcc doesn't seem to be too good at common      */
973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* expression substitution and instruction scheduling ;-)          */
974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Cubic                                                        */
981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
983174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide a third-order Bezier arc into two joint sub-arcs in the  */
984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier stack.                                                      */
985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of the component.  It is one of _the_   */
988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    inner loops that should be optimized like hell to get the best     */
989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    performance.                                                       */
990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
99152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
99252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Cubic( TPoint*  base )
993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b, c, d;
995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].x = base[3].x;
998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].x;
999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].x;
1000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
1001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
1002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
1003a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = a = ( a + c + 1 ) >> 1;
1004a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = b = ( b + c + 1 ) >> 1;
1005a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].x = ( a + b + 1 ) >> 1;
1006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].y = base[3].y;
1008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].y;
1009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].y;
1010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
1011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
1012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
1013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = a = ( a + c + 1 ) >> 1;
1014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = b = ( b + c + 1 ) >> 1;
1015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].y = ( a + b + 1 ) >> 1;
1016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Up                                                            */
1023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1025174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending line segment and store   */
1026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
1030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
1032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
1034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
1036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
1038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
1040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
104452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
104552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Up( RAS_ARGS Long  x1,
104652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y1,
104752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  x2,
104852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y2,
104952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  miny,
105052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  maxy )
1051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Dx, Dy;
1053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
1054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Ix, Rx, Ax;
1055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong  top;
1057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dx = x2 - x1;
1060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dy = y2 - y1;
1061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dy <= 0 || y2 < miny || y1 > maxy )
1063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return SUCCESS;
1064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
1066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* Take care: miny-y1 can be a very large value; we use     */
1068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /*            a slow MulDiv function to avoid clipping bugs */
1069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += SMulDiv( Dx, miny - y1, Dy );
107073861976779a754cc9b808760cc8e6cf98d52549Werner Lemberg      e1  = (Int)TRUNC( miny );
1071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f1  = 0;
1072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1073a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
107568e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e1 = (Int)TRUNC( y1 );
107668e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f1 = (Int)FRAC( y1 );
1077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 > maxy )
1080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1081a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
108268e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2  = (Int)TRUNC( maxy );
1083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f2  = 0;
1084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
108768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2 = (Int)TRUNC( y2 );
108868e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f2 = (Int)FRAC( y2 );
1089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( f1 > 0 )
1092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
1094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return SUCCESS;
1095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
1098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 += 1;
1099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.joint )
1103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.top--;
1105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.joint = FALSE;
1106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
11088edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    ras.joint = (char)( f2 == 0 );
1109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = e1;
1113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh           = FALSE;
1114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    size = e2 - e1 + 1;
1117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top + size >= ras.maxBuff )
1118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
1120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dx > 0 )
1124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ix = ( ras.precision * Dx ) / Dy;
1126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Rx = ( ras.precision * Dx ) % Dy;
1127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = 1;
1128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ix = -( ( ras.precision * -Dx ) / Dy );
1132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Rx =    ( ras.precision * -Dx ) % Dy;
1133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = -1;
1134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Ax  = -Dy;
1137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( size > 0 )
1140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *top++ = x1;
1142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += Ix;
1144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ax += Rx;
1145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Ax >= 0 )
1146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Ax -= Dy;
1148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        x1 += Dx;
1149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      size--;
1151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top = top;
1154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Down                                                          */
1162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1164174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending line segment and store  */
1165174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    them in the render pool.                                           */
1166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
1169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
1171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
1173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
1175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
1177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
1179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
118352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
118452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Down( RAS_ARGS Long  x1,
118552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y1,
118652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  x2,
118752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y2,
118852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  miny,
118952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  maxy )
1190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool  result, fresh;
1192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh  = ras.fresh;
1195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A function type describing the functions used to split Bezier arcs */
1206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef void  (*TSplitter)( TPoint*  base );
1207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1212a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Up                                                          */
1213a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1214a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1215174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending Bezier arc and store     */
1216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
123052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
123152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Up( RAS_ARGS Int        degree,
123252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      TSplitter  splitter,
123352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       miny,
123452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       maxy )
1235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   y1, y2, e, e2, e0;
1237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  f1;
1238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc;
1240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  start_arc;
1241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong top;
1243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc = ras.arc;
1246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y1  = arc[degree].y;
1247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y2  = arc[0].y;
1248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 < miny || y1 > maxy )
1251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e2 = FLOOR( y2 );
1254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 > maxy )
1256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = maxy;
1257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e0 = miny;
1259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
1261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e = miny;
1262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e  = CEILING( y1 );
1265914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( FRAC( y1 ) );
1266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e0 = e;
1267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( f1 == 0 )
1269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.joint )
1271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          top--;
1273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint = FALSE;
1274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *top++ = arc[degree].x;
1277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e += ras.precision;
1279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = TRUNC( e0 );
1285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh = FALSE;
1286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 < e )
1289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top   = top;
1294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Overflow;
1295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start_arc = arc;
1299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( arc >= start_arc && e <= e2 )
1301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.joint = FALSE;
1303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = arc[0].y;
1305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 > e )
1307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y1 = arc[degree].y;
1309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 - y1 >= ras.precision_step )
1310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          splitter( arc );
1312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc += degree;
1313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1316cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
1317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                            e - y1, y2 - y1 );
1318a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc -= degree;
1319a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e   += ras.precision;
1320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1323a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 == e )
1325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint  = TRUE;
1327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *top++     = arc[0].x;
1328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e += ras.precision;
1330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        arc -= degree;
1332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fin:
1336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top  = top;
1337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc -= degree;
1338a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1339a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Down                                                        */
1346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1348174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending Bezier arc and store    */
1349a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1361a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
136352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
136452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Down( RAS_ARGS Int        degree,
136552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        TSplitter  splitter,
136652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       miny,
136752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       maxy )
1368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc = ras.arc;
1370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool     result, fresh;
1371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[1].y = -arc[1].y;
1375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[2].y = -arc[2].y;
1376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( degree > 2 )
1377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      arc[3].y = -arc[3].y;
1378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh = ras.fresh;
1380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1382a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1387a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_To                                                            */
1395a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1396a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1397174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new line segment and adjust the Profiles list.            */
1398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1399a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x :: The x-coordinate of the segment's end point (its start point   */
1401ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastX').                                         */
1402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1403a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y :: The y-coordinate of the segment's end point (its start point   */
1404ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastY').                                         */
1405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1406a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1407a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
141052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
141152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_To( RAS_ARGS Long  x,
141252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y )
1413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, detect a change of direction */
1415a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
14189ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Unknown_State:
1419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
142142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( New_Profile( RAS_VARS Ascending_State,
142242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1423a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1427a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < ras.lastY )
142842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS Descending_State,
142942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
1430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return FAILURE;
1431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
14349ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y < ras.lastY )
1436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
143742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
143842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             New_Profile( RAS_VARS Descending_State,
143942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
1440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
14449ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
144742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
144842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             New_Profile( RAS_VARS Ascending_State,
144942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1455a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1456a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1457a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then compute the lines */
1459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1460a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
14629ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
146442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             x, y, ras.minY, ras.maxY ) )
1465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1466a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1467a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
14689ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
147042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                               x, y, ras.minY, ras.maxY ) )
1471a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x;
1479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y;
1480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Conic_To                                                           */
1489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1491174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new conic arc and adjust the profile list.                */
1492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx :: The x-coordinate of the arc's new control point.              */
1495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy :: The y-coordinate of the arc's new control point.              */
1497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
1499ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastX').                                           */
1500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
1502ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastY').                                           */
1503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
150852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
150952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Conic_To( RAS_ARGS Long  cx,
151052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy,
151152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
151252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, x3, ymin, ymax;
1515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].x = ras.lastX;
1520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].y = ras.lastY;
1521cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].x = cx;
1522cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].y = cy;
1523cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].x = x;
1524cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].y = y;
1525a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1526a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1527a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[2].y;
1529a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[1].y;
1530a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[0].y;
1531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x3 = ras.arc[0].x;
1532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1533a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1534a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1535a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y3 )
1536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y1;
1538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y3;
1539a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y3;
1543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y1;
1544a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1545a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1546a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 < ymin || y2 > ymax )
1547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1548a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1549a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Conic( ras.arc );
1550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 2;
1551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y3 )
1553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1554a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 2;
1556a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the arc is y-monotonous, either ascending or descending */
1560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction                            */
15619ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = y1 < y3 ? Ascending_State : Descending_State;
1562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
156442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          Bool  o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
156542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                                 : IS_TOP_OVERSHOOT( y1 );
156642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
156742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
1568a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* finalize current profile if any */
1569cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          if ( ras.state != Unknown_State &&
157042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               End_Profile( RAS_VARS o )  )
1571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* create a new profile */
157442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS state_bez, o ) )
1575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* now call the appropriate routine */
15799ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1585a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1587a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1588a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1590a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1591a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x3;
1592a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y3;
1593a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1594a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1595a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1596a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1603a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1604a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Cubic_To                                                           */
1605a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1606a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1607174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new cubic arc and adjust the profile list.                */
1608a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1609a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
1611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
1613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
1615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
1617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
1619ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastX').                                          */
1620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
1622ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastY').                                          */
1623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
162852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
162952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Cubic_To( RAS_ARGS Long  cx1,
163052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy1,
163152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cx2,
163252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy2,
163352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
163452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].x = ras.lastX;
1642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].y = ras.lastY;
1643cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[2].x = cx1;
1644cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[2].y = cy1;
1645cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].x = cx2;
1646cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].y = cy2;
1647cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].x = x;
1648cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].y = y;
1649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1652a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[3].y;
1653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[2].y;
1654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[1].y;
1655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y4 = ras.arc[0].y;
1656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x4 = ras.arc[0].x;
1657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y4 )
1661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y1;
1663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y4;
1664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y4;
1668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y1;
1669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 <= y3 )
1672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y2;
1674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y3;
1675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y3;
1679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y2;
1680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ymin2 < ymin1 || ymax2 > ymax1 )
1683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Cubic( ras.arc );
1686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 3;
1687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1688a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y4 )
1689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 3;
1692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
16959ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction */
1698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
170042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          Bool  o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
170142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                                 : IS_TOP_OVERSHOOT( y1 );
170242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
170342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
170442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* finalize current profile if any */
1705cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          if ( ras.state != Unknown_State &&
170642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               End_Profile( RAS_VARS o )  )
1707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
170942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS state_bez, o ) )
1710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* compute intersections */
17149ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x4;
1727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y4;
1728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  SWAP_
1737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SWAP_( x, y )  do                \
1738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       {                 \
1739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         Long  swap = x; \
1740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         x = y;          \
1743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         y = swap;       \
1744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       } while ( 0 )
1745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Decompose_Curve                                                    */
1751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1753174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Scan the outline arrays in order to emit individual segments and   */
1754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
1755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    weird cases, like when the first point is off the curve, or when   */
1756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    there are simply no `on' points in the contour!                    */
1757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    first   :: The index of the first point in the contour.            */
1760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    last    :: The index of the last point in the contour.             */
1762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1763a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the curve.                */
1764a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on error.                              */
1767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
176852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
176952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Decompose_Curve( RAS_ARGS UShort  first,
177052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                            UShort  last,
177152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                            int     flipped )
1772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_last;
1774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_control;
1775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_start;
1776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  points;
1778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  point;
1779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  limit;
1780a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    char*       tags;
1781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
17828edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    unsigned    tag;       /* current point's state           */
1783a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    points = ras.outline.points;
1786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    limit  = points + last;
1787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.x = SCALED( points[first].x );
1789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.y = SCALED( points[first].y );
1790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.x  = SCALED( points[last].x );
1791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.y  = SCALED( points[last].y );
1792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( flipped )
1794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_start.x, v_start.y );
1796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_last.x, v_last.y );
1797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1799a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_control = v_start;
1800a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    point = points + first;
1802cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    tags  = ras.outline.tags + first;
180372271140434028186a49a5dc5925f0727559e46fWerner Lemberg
180472271140434028186a49a5dc5925f0727559e46fWerner Lemberg    /* set scan mode if necessary */
180572271140434028186a49a5dc5925f0727559e46fWerner Lemberg    if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE )
180672271140434028186a49a5dc5925f0727559e46fWerner Lemberg      ras.dropOutControl = (Byte)tags[0] >> 5;
180772271140434028186a49a5dc5925f0727559e46fWerner Lemberg
180872271140434028186a49a5dc5925f0727559e46fWerner Lemberg    tag = FT_CURVE_TAG( tags[0] );
1809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* A contour cannot start with a cubic control point! */
1811b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CUBIC )
1812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Invalid_Outline;
1813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* check first point to determine origin */
1815b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CONIC )
1816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first point is conic control.  Yes, this happens. */
1818b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at last point if it is on the curve */
1821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start = v_last;
1822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        limit--;
1823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* if both first and last points are conic,         */
1827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at their middle and record its position    */
1828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* for closure                                      */
1829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.x = ( v_start.x + v_last.x ) / 2;
1830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.y = ( v_start.y + v_last.y ) / 2;
1831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_last = v_start;
1833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point--;
1835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags--;
1836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = v_start.x;
1839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = v_start.y;
1840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( point < limit )
1842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point++;
1844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags++;
1845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tag = FT_CURVE_TAG( tags[0] );
1847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      switch ( tag )
1849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1850b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_ON:  /* emit a single line_to */
1851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x, y;
1853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point->x );
1856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point->y );
1857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Line_To( RAS_VARS x, y ) )
1861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          continue;
1863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1865b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
1866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.x = SCALED( point[0].x );
1867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.y = SCALED( point[0].y );
1868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( flipped )
1870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          SWAP_( v_control.x, v_control.y );
1871a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Do_Conic:
1873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( point < limit )
1874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          FT_Vector  v_middle;
1876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long       x, y;
1877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point++;
1880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags++;
1881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tag = FT_CURVE_TAG( tags[0] );
1882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point[0].x );
1884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point[0].y );
1885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1889b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag == FT_CURVE_TAG_ON )
1890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1896b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag != FT_CURVE_TAG_CONIC )
1897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.x = ( v_control.x + x ) / 2;
1900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.y = ( v_control.y + y ) / 2;
1901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                  v_middle.x,  v_middle.y ) )
1904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1905a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.x = x;
1907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.y = y;
1908a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Do_Conic;
1910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                v_start.x,   v_start.y ) )
1914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Fail;
1915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        goto Close;
1917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1918b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      default:  /* FT_CURVE_TAG_CUBIC */
1919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x1, y1, x2, y2, x3, y3;
1921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point + 1 > limit                             ||
1924b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner               FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point += 2;
1928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags  += 2;
1929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = SCALED( point[-2].x );
1931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y1 = SCALED( point[-2].y );
1932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = SCALED( point[-1].x );
1933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y2 = SCALED( point[-1].y );
1934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x3 = SCALED( point[ 0].x );
1935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y3 = SCALED( point[ 0].y );
1936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x1, y1 );
1940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x2, y2 );
1941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x3, y3 );
1942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point <= limit )
1945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Close;
1954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* close the contour with a line segment */
1959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fail;
1961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Close:
1963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Invalid_Outline:
1966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.error = Raster_Err_Invalid;
1967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Convert_Glyph                                                      */
1977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1979174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Convert a glyph into a series of segments and arcs and make a      */
1980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    profiles list with them.                                           */
1981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of curve.                    */
1984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE if any error was encountered during    */
1987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    rendering.                                                         */
1988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
198952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
199052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Convert_Glyph( RAS_ARGS int  flipped )
1991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
19928edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    int       i;
19938edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    unsigned  start;
1994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  lastProfile;
1996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fProfile = NULL;
1999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint    = FALSE;
2000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh    = FALSE;
2001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
2003a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2004a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.numTurns = 0;
2005a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile         = (PProfile)ras.top;
2007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->offset = ras.top;
2008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.num_Profs        = 0;
2009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start = 0;
2011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    for ( i = 0; i < ras.outline.n_contours; i++ )
2013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
201442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      Bool  o;
201542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
201642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
20179ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg      ras.state    = Unknown_State;
2018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = NULL;
2019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
20208eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      if ( Decompose_Curve( RAS_VARS (unsigned short)start,
202142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                     ras.outline.contours[i],
202242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                     flipped ) )
2023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
2024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2025a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      start = ras.outline.contours[i] + 1;
2026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2027cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg      /* we must now check whether the extreme arcs join or not */
2028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( FRAC( ras.lastY ) == 0 &&
2029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY >= ras.minY  &&
2030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY <= ras.maxY  )
203142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( ras.gProfile                        &&
203242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             ( ras.gProfile->flags & Flow_Up ) ==
203342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               ( ras.cProfile->flags & Flow_Up ) )
2034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.top--;
2035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* Note that ras.gProfile can be nil if the contour was too small */
2036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* to be drawn.                                                   */
2037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      lastProfile = ras.cProfile;
203942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( ras.cProfile->flags & Flow_Up )
204042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        o = IS_TOP_OVERSHOOT( ras.lastY );
204142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      else
204242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
204342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( End_Profile( RAS_VARS o ) )
2044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
2045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2046a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* close the `next profile in contour' linked list */
2047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.gProfile )
2048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        lastProfile->next = ras.gProfile;
2049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Finalize_Profile_Table( RAS_VAR ) )
2052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
2053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
20548edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
2055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
2061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
2062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
2063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Init_Linked                                                          */
2070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Initializes an empty linked list.                                  */
2072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
207352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
207452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Init_Linked( TProfileList*  l )
2075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *l = NULL;
2077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2081a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2082a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  InsNew                                                               */
2083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Inserts a new profile in a linked list.                            */
2085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
208652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
208752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  InsNew( PProfileList  list,
208852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
2089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
2091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long       x;
2092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    x       = profile->X;
2097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
2099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( x < current->X )
2101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        break;
2102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
2103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
2104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    profile->link = current;
2107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *old          = profile;
2108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  DelOld                                                               */
2114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Removes an old profile from a linked list.                         */
2116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
211752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
211852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  DelOld( PProfileList  list,
211952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
2120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
2122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
2128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current == profile )
2130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old = current->link;
2132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
2136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
2137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* we should never get there, unless the profile was not part of */
2140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* the list.                                                     */
2141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Sort                                                                 */
2147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
2149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
2150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    and simple.                                                        */
2151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
215252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
215352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Sort( PProfileList  list )
2154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current, next;
2156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, set the new X coordinate of each profile */
2159ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    current = *list;
2160ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    while ( current )
2161ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    {
2162ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->X       = *current->offset;
216390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg      current->offset += current->flags & Flow_Up ? 1 : -1;
2164ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->height--;
2165ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current = current->link;
2166ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    }
2167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then sort them */
2169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !current )
2173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return;
2174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    next = current->link;
2176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( next )
2178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current->X <= next->X )
2180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = &current->link;
2182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( !current )
2185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return;
2186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old          = next;
2190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current->link = next->link;
2191a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        next->link    = current;
2192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = list;
2194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      next = current->link;
2198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Vertical Sweep Procedure Set                                         */
2205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the vertical black/white sweep   */
2207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  phase by the generic Draw_Sweep() function.                          */
2208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
221152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
221252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Init( RAS_ARGS Short*  min,
221352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max )
2214a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2215a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  pitch = ras.target.pitch;
2216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceIncr = (Short)-pitch;
2221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs  = -*min * pitch;
2222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( pitch > 0 )
2223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
2224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_min_x = 0;
2226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_max_x = 0;
2227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
223052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
223152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Span( RAS_ARGS Short       y,
223252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
223352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
223452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
223552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
22388edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    int    c1, c2;
2239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1, f2;
2240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte*  target;
2241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( y );
2243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e1 = TRUNC( CEILING( x1 ) );
2250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
2252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = e1;
2253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
2254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = TRUNC( FLOOR( x2 ) );
2255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 >= 0 && e1 < ras.bWidth )
2257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 < 0 )
2259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = 0;
2260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e2 >= ras.bWidth )
2261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e2 = ras.bWidth - 1;
2262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 = (Short)( e2 >> 3 );
2265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22668edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
22678edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22695df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_min_x > c1 )
22705df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_min_x = (short)c1;
22715df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_max_x < c2 )
22725df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_max_x = (short)c2;
2273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      target = ras.bTarget + ras.traceOfs + c1;
2275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 -= c1;
2276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( c2 > 0 )
2278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[0] |= f1;
2280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
228194ffae5239631a18b8b5a39674c0afa8a992410eWerner Lemberg        /* memset() is slower than the following code on many platforms. */
2282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* This is due to the fact that, in the vast majority of cases,  */
2283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the span length in bytes is relatively small.                 */
2284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        c2--;
2285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( c2 > 0 )
2286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *(++target) = 0xFF;
2288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2--;
2289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[1] |= f2;
2291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *target |= ( f1 & f2 );
2294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
229852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
229952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Drop( RAS_ARGS Short       y,
230052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
230152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
230252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
230352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
23055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  c1, f1;
2307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   e2            x2                    x1           e1   */
23125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
23135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 ^                     |                 */
23145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
23155df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   +-------------+---------------------+------------+    */
23165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
23175df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     v                 */
23185df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
23195df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* pixel         contour              contour       pixel  */
23205df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* center                                           center */
23215df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
23225df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* drop-out mode    scan conversion rules (as defined in OpenType) */
23235df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* --------------------------------------------------------------- */
23245df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  0                1, 2, 3                                       */
23255df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  1                1, 2, 4                                       */
23265df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  2                1, 2                                          */
23275df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  3                same as mode 2                                */
23285df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  4                1, 2, 5                                       */
23295df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  5                1, 2, 6                                       */
23305df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  6, 7             same as mode 2                                */
23315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
23325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
23335df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
23345df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
233872271140434028186a49a5dc5925f0727559e46fWerner Lemberg      Int  dropOutControl = left->flags & 7;
233972271140434028186a49a5dc5925f0727559e46fWerner Lemberg
234072271140434028186a49a5dc5925f0727559e46fWerner Lemberg
2341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
234372271140434028186a49a5dc5925f0727559e46fWerner Lemberg        switch ( dropOutControl )
2344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
23455df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
23465df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23495df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
23502f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg          pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23535df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
23545df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
2355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23565df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* Drop-out Control Rules #4 and #6 */
23575df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
235842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* The specification neither provides an exact definition */
235942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* of a `stub' nor gives exact rules to exclude them.     */
2360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
236142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* Here the constraints we use to recognize a stub.       */
2362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2363a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  upper stub:                                           */
2364a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Right is the successor of P_Left in that contour */
2367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the top of P_Left and P_Right                 */
2368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  lower stub:                                           */
2370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left is the successor of P_Right in that contour */
2373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the bottom of P_Left                          */
2374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
237542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* We draw a stub if the following constraints are met.   */
237642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*                                                        */
237742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*   - for an upper or lower stub, there is top or bottom */
237842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*     overshoot, respectively                            */
237942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*   - the covered interval is greater or equal to a half */
238042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*     pixel                                              */
238142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
238242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* upper stub test */
238342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( left->next == right                &&
238442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->height <= 0                  &&
238542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Top   &&
238642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half ) )
238742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg            return;
2388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
238942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* lower stub test */
239042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( right->next == left                 &&
239142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->start == y                    &&
239242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Bottom &&
239342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half  ) )
239442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg            return;
2395a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
239672271140434028186a49a5dc5925f0727559e46fWerner Lemberg          if ( dropOutControl == 1 )
23975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
23985df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
23992f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg            pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
24005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
24035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
24045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
24075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = pxl == e1 ? e2 : e1;
2408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        c1 = (Short)( e1 >> 3 );
24125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1 = (Short)( e1 &  7 );
2413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( e1 >= 0 && e1 < ras.bWidth                      &&
24155df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
24165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;
2417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24225df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2423a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 && e1 < ras.bWidth )
2425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2427914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( e1 & 7 );
2428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24295df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_min_x > c1 )
24305df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_min_x = c1;
24315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.gray_max_x < c1 )
24325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.gray_max_x = c1;
2433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
243952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
244052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Step( RAS_ARG )
2441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs += ras.traceIncr;
2443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2448a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Horizontal Sweep Procedure Set                                     */
2449a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the horizontal black/white     */
2451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  sweep phase by the generic Draw_Sweep() function.                  */
2452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
245552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
245652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
245752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  Short*  max )
2458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing, really */
2460f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( min );
2462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
246652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
246752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Span( RAS_ARGS Short       y,
246852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
246952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
247052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
247152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
2474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  bits;
2475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1;
2476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( x2 - x1 < ras.precision )
2482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e1 = CEILING( x1 );
2484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = FLOOR  ( x2 );
2485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
2487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        bits = ras.bTarget + ( y >> 3 );
2489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        f1   = (Byte)( 0x80 >> ( y & 7 ) );
2490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = TRUNC( e1 );
2492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( e1 >= 0 && e1 < ras.target.rows )
2494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          PByte  p;
2496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p = bits - e1*ras.target.pitch;
2499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( ras.target.pitch > 0 )
2500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            p += ( ras.target.rows - 1 ) * ras.target.pitch;
2501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p[0] |= f1;
2503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
250952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
251052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
251152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
251252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
251352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
251452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
25165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  bits;
2518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1;
2519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2521a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* During the horizontal sweep, we only take care of drop-outs */
2522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25235df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e1     +       <-- pixel center */
25245df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25255df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x1  ---+-->    <-- contour      */
25265df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25275df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25285df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x2  <--+---    <-- contour      */
25295df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25305df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e2     +       <-- pixel center */
25325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
25335df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
25345df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
25355df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
253972271140434028186a49a5dc5925f0727559e46fWerner Lemberg      Int  dropOutControl = left->flags & 7;
254072271140434028186a49a5dc5925f0727559e46fWerner Lemberg
254172271140434028186a49a5dc5925f0727559e46fWerner Lemberg
2542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
254472271140434028186a49a5dc5925f0727559e46fWerner Lemberg        switch ( dropOutControl )
2545a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
25465df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
25475df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2548a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2549a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25505df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
25512f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg          pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25545df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
25555df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
25565df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* see Vertical_Sweep_Drop for details */
2557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* rightmost stub test */
255942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( left->next == right                &&
256042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->height <= 0                  &&
256142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Top   &&
256242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half ) )
2563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2564a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2565a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* leftmost stub test */
256642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( right->next == left                 &&
256742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->start == y                    &&
256842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Bottom &&
256942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half  ) )
2570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
257272271140434028186a49a5dc5925f0727559e46fWerner Lemberg          if ( dropOutControl == 1 )
25735df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
25745df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
25752f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg            pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
25765df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
25795df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
25805df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
25835df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = pxl == e1 ? e2 : e1;
2584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25875df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits = ras.bTarget + ( y >> 3 );
25885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1   = (Byte)( 0x80 >> ( y & 7 ) );
2589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits -= e1 * ras.target.pitch;
25915df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( ras.target.pitch > 0 )
25925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2593a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( e1 >= 0              &&
25955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             e1 < ras.target.rows &&
25965df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             *bits & f1           )
25975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;
2598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2603a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    bits = ras.bTarget + ( y >> 3 );
2604a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    f1   = (Byte)( 0x80 >> ( y & 7 ) );
2605a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2607a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2608a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 && e1 < ras.target.rows )
2609a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits -= e1 * ras.target.pitch;
2611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.target.pitch > 0 )
2612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits[0] |= f1;
2615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
261952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
262052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Step( RAS_ARG )
2621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2622a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Nothing, really */
2623f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
2628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2631a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2632a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Vertical Gray Sweep Procedure Set                                    */
2633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These two routines are used during the vertical gray-levels sweep    */
2635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  phase by the generic Draw_Sweep() function.                          */
2636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  NOTES                                                                */
2638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  - The target pixmap's width *must* be a multiple of 4.               */
2640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
2642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    span call.                                                         */
2643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
264652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
264752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
264852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                     Short*  max )
2649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  pitch, byte_len;
2651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2652a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *min = *min & -2;
2654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *max = ( *max + 3 ) & -2;
2655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs  = 0;
2657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    pitch         = ras.target.pitch;
2658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    byte_len      = -pitch;
2659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceIncr = (Short)byte_len;
2660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceG    = ( *min / 2 ) * byte_len;
2661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( pitch > 0 )
2663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceG += ( ras.target.rows - 1 ) * pitch;
2665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      byte_len    = -byte_len;
2666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_min_x =  (Short)byte_len;
2669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gray_max_x = -(Short)byte_len;
2670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
267352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
267452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Gray_Sweep_Step( RAS_ARG )
2675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2676766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    Int     c1, c2;
2677766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    PByte   pix, bit, bit2;
2678766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    short*  count = (short*)count_table;
2679766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    Byte*   grays;
2680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs += ras.gray_width;
2683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.traceOfs > ras.gray_width )
2685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
2687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      grays = ras.grays;
2688a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.gray_max_x >= 0 )
2690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2691174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Long  last_pixel = ras.target.width - 1;
2692174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Int   last_cell  = last_pixel >> 2;
2693174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Int   last_bit   = last_pixel & 3;
2694174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        Bool  over       = 0;
2695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
2698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.gray_max_x = last_cell - 1;
2700a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          over = 1;
2701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.gray_min_x < 0 )
2704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.gray_min_x = 0;
2705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2706174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        bit  = ras.bTarget + ras.gray_min_x;
2707174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        bit2 = bit + ras.gray_width;
2708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        c1 = ras.gray_max_x - ras.gray_min_x;
2710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( c1 >= 0 )
2712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2 = count[*bit] + count[*bit2];
2714a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( c2 )
2716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[0] = grays[(c2 >> 12) & 0x000F];
2718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[1] = grays[(c2 >> 8 ) & 0x000F];
2719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[2] = grays[(c2 >> 4 ) & 0x000F];
2720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            pix[3] = grays[ c2        & 0x000F];
2721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit  = 0;
2723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit2 = 0;
2724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          bit++;
2727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          bit2++;
2728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pix += 4;
2729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c1--;
2730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( over )
2733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2 = count[*bit] + count[*bit2];
2735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( c2 )
2736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            switch ( last_bit )
2738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            {
2739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            case 2:
2740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[2] = grays[(c2 >> 4 ) & 0x000F];
2741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            case 1:
2742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[1] = grays[(c2 >> 8 ) & 0x000F];
2743a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            default:
2744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              pix[0] = grays[(c2 >> 12) & 0x000F];
2745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            }
2746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit  = 0;
2748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            *bit2 = 0;
2749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceOfs = 0;
2754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.traceG  += ras.traceIncr;
2755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gray_min_x =  32000;
2757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gray_max_x = -32000;
2758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
276252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
276352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
276452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x1,
276552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x2,
276652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    left,
276752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    right )
2768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing, really */
2770f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( y );
2772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( x1 );
2773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( x2 );
2774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
277952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
278052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
278152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x1,
278252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       FT_F26Dot6  x2,
278352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    left,
278452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                       PProfile    right )
2785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
2787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  pixel;
2788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   color;
2789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* During the horizontal sweep, we only take care of drop-outs */
27925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
2793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e1 = CEILING( x1 );
2794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e2 = FLOOR  ( x2 );
2795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
279872271140434028186a49a5dc5925f0727559e46fWerner Lemberg      Int  dropOutControl = left->flags & 7;
279972271140434028186a49a5dc5925f0727559e46fWerner Lemberg
280072271140434028186a49a5dc5925f0727559e46fWerner Lemberg
2801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
280372271140434028186a49a5dc5925f0727559e46fWerner Lemberg        switch ( dropOutControl )
2804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
28055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
2806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e1 = e2;
2807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
28102f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg          e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
28145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
28155df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* see Vertical_Sweep_Drop for details */
2816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* rightmost stub test */
2818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( left->next == right && left->height <= 0 )
2819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* leftmost stub test */
2822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( right->next == left && left->start == y )
2823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return;
2824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
282572271140434028186a49a5dc5925f0727559e46fWerner Lemberg          if ( dropOutControl == 1 )
2826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            e1 = e2;
2827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          else
28282f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg            e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
28335df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          return;  /* no drop-out control */
2834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 )
2841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( x2 - x1 >= ras.precision_half )
2843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        color = ras.grays[2];
2844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        color = ras.grays[1];
2846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e1 = TRUNC( e1 ) / 2;
2848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 < ras.target.rows )
2849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
2851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.target.pitch > 0 )
2852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
2853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( pixel[0] == ras.grays[0] )
2855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          pixel[0] = color;
2856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
2862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Generic Sweep Drawing routine                                        */
2867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
287052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
287152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Draw_Sweep( RAS_ARG )
2872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         y, y_change, y_height;
2874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile      P, Q, P_Left, P_Right;
2876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         min_Y, max_Y, top, bottom, dropouts;
2878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long          x1, x2, xs, e1, e2;
2880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28813c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    TProfileList  waiting;
2882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TProfileList  draw_left, draw_right;
2883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2885174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* initialize empty linked lists */
2886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
28873c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    Init_Linked( &waiting );
2888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_left  );
2890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_right );
2891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* first, compute min and max Y */
2893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P     = ras.fProfile;
2895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    max_Y = (Short)TRUNC( ras.minY );
2896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    min_Y = (Short)TRUNC( ras.maxY );
2897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Q = P->link;
2901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bottom = (Short)P->start;
2903914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      top    = (Short)( P->start + P->height - 1 );
2904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
29055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( min_Y > bottom )
29065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        min_Y = bottom;
29075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( max_Y < top )
29085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        max_Y = top;
2909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P->X = 0;
29113c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      InsNew( &waiting, P );
2912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = Q;
2914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2916174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* check the Y-turns */
2917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.numTurns == 0 )
2918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_Invalid;
2920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
2921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2923174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* now initialize the sweep */
2924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2927174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* then compute the distance of each profile from min_Y */
2928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
29293c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    P = waiting;
2930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2933914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      P->countL = (UShort)( P->start - min_Y );
2934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = P->link;
2935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2937174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* let's go */
2938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y        = min_Y;
2940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_height = 0;
2941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2942cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    if ( ras.numTurns > 0                     &&
2943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner         ras.sizeBuff[-ras.numTurns] == min_Y )
2944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns--;
2945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.numTurns > 0 )
2947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2948174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* check waiting list for new activations */
2949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
29503c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      P = waiting;
2951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P->countL -= y_height;
2956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->countL == 0 )
2957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
29583c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg          DelOld( &waiting, P );
2959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
296090c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          if ( P->flags & Flow_Up )
2961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_left,  P );
296290c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          else
2963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_right, P );
2964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2969174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* sort the drawing lists */
2970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_left );
2972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_right );
2973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
29758eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      y_height = (Short)( y_change - y );
2976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( y < y_change )
2978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2979174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* let's trace */
2980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts = 0;
2982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left  = draw_left;
2984a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Right = draw_right;
2985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( P_Left )
2987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = P_Left ->X;
2989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = P_Right->X;
2990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( x1 > x2 )
2992a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            xs = x1;
2994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x1 = x2;
2995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x2 = xs;
2996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
299871b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e1 = FLOOR( x1 );
299971b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e2 = CEILING( x2 );
3000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
300171b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          if ( x2 - x1 <= ras.precision &&
300271b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg               e1 != x1 && e2 != x2     )
300371b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          {
3004ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg            if ( e1 > e2 || e2 == e1 + ras.precision )
3005a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            {
300672271140434028186a49a5dc5925f0727559e46fWerner Lemberg              Int  dropOutControl = P_Left->flags & 7;
300772271140434028186a49a5dc5925f0727559e46fWerner Lemberg
300872271140434028186a49a5dc5925f0727559e46fWerner Lemberg
300972271140434028186a49a5dc5925f0727559e46fWerner Lemberg              if ( dropOutControl != 2 )
3010ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              {
3011174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                /* a drop-out was detected */
3012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3013ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left ->X = x1;
3014ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Right->X = x2;
3015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3016ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                /* mark profile for drop-out processing */
3017ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left->countL = 1;
3018ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                dropouts++;
3019ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              }
3020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Skip_To_Next;
3022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            }
3023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
3024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3025a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
3026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Skip_To_Next:
3028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Left  = P_Left->link;
3030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Right = P_Right->link;
3031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
3032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3033174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* handle drop-outs _after_ the span drawing --       */
3034174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* drop-out processing has been moved out of the loop */
3035174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* for performance tuning                             */
3036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( dropouts > 0 )
3037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Scan_DropOuts;
3038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Next_Line:
3040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Step( RAS_VAR );
3042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y++;
3044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < y_change )
3046a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
3047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_left  );
3048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_right );
3049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
3050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3052174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* now finalize the profiles that need it */
3053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_left;
3055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
3056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
3058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
3059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_left, P );
3060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
3061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_right;
3064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
3065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
3067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
3068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_right, P );
3069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
3070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3073174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* for gray-scaling, flush the bitmap scanline cache */
3074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( y <= max_Y )
3075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step( RAS_VAR );
3077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y++;
3078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
3081a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3082a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Scan_DropOuts:
3083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Left  = draw_left;
3085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Right = draw_right;
3086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P_Left )
3088a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( P_Left->countL )
3090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left->countL = 0;
3092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#if 0
3093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts--;  /* -- this is useful when debugging only */
3094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Drop( RAS_VARS y,
3096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left->X,
3097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right->X,
3098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left,
3099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right );
3100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Left  = P_Left->link;
3103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Right = P_Right->link;
3104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    goto Next_Line;
3107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
3111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
3113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Single_Pass                                                 */
3114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
3116174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Perform one sweep with sub-banding.                                */
3117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
3119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the outline.              */
3120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
3122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Renderer error code.                                               */
3123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
312452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
312552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Single_Pass( RAS_ARGS Bool  flipped )
3126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  i, j, k;
3128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.band_top >= 0 )
3131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
3133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
3134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top = ras.buff;
3136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_None;
3138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Convert_Glyph( RAS_VARS flipped ) )
3140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.error != Raster_Err_Overflow )
3142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
3143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.error = Raster_Err_None;
3145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* sub-banding */
3147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef DEBUG_RASTER
3149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
3150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        i = ras.band_stack[ras.band_top].y_min;
3153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        j = ras.band_stack[ras.band_top].y_max;
3154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31558eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        k = (Short)( ( i + j ) / 2 );
3156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.band_top >= 7 || k < i )
3158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
3159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.band_top = 0;
3160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.error    = Raster_Err_Invalid;
3161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return ras.error;
3163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
3164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_min = k;
3166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_max = j;
3167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31688eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
3169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top++;
3171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
3173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
3174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.fProfile )
3175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Draw_Sweep( RAS_VAR ) )
3176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner             return ras.error;
3177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top--;
3178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
3179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
3182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
3186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
3188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Glyph                                                       */
3189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
3191174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Render a glyph in a bitmap.  Sub-banding if needed.                */
3192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
3194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    FreeType error code.  0 means success.                             */
3195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3196bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
319752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Glyph( RAS_ARG )
3198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
3200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Set_High_Precision( RAS_VARS ras.outline.flags &
320342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                 FT_OUTLINE_HIGH_PRECISION );
32045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.scale_shift = ras.precision_shift;
32055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
32075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      ras.dropOutControl = 2;
32085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    else
32095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    {
32105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
32115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 4;
32125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      else
32135df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 0;
32145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32155df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
32165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl += 1;
32175df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    }
32185df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32195df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.second_pass = (FT_Byte)( !( ras.outline.flags &
32205df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg                                    FT_OUTLINE_SINGLE_PASS ) );
3221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Vertical Sweep */
3223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
3224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
3227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_top            = 0;
3229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_min = 0;
32308eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
3231a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
32328edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    ras.bWidth  = (unsigned short)ras.target.width;
3233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bTarget = (Byte*)ras.target.buffer;
3234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
3236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return error;
3237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Horizontal Sweep */
3239ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg    if ( ras.second_pass && ras.dropOutControl != 2 )
3240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_top            = 0;
3247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_min = 0;
32488eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
3249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return error;
3252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3254f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_None;
3255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
3259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
3261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
3263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Gray_Glyph                                                  */
3264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
3266174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Render a glyph with grayscaling.  Sub-banding if needed.           */
3267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
3269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    FreeType error code.  0 means success.                             */
3270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
3271bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
327252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Gray_Glyph( RAS_ARG )
3273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long      pixel_width;
3275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
3276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Set_High_Precision( RAS_VARS ras.outline.flags &
327942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                 FT_OUTLINE_HIGH_PRECISION );
32805df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.scale_shift = ras.precision_shift + 1;
32815df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
32835df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      ras.dropOutControl = 2;
32845df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    else
32855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    {
32865df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
32875df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 4;
32885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      else
32895df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 0;
32905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32915df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
32925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl += 1;
32935df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    }
32945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
32955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
3296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Vertical Sweep */
3298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_top            = 0;
3300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_min = 0;
3301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
3302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bWidth  = ras.gray_width;
3304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
3305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.bWidth > pixel_width )
3307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.bWidth = pixel_width;
3308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bWidth  = ras.bWidth * 8;
3310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bTarget = (Byte*)ras.gray_lines;
3311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.gTarget = (Byte*)ras.target.buffer;
3312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
3314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
3317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3318a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    error = Render_Single_Pass( RAS_VARS 0 );
3319a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( error )
3320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return error;
3321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Horizontal Sweep */
3323ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg    if ( ras.second_pass && ras.dropOutControl != 2 )
3324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3325a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3326a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
3327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
3328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_top            = 0;
3331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_min = 0;
3332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
3333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      error = Render_Single_Pass( RAS_VARS 1 );
3335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( error )
3336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return error;
3337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3338a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3339f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_None;
3340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3342bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
3343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3344bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  FT_LOCAL_DEF( FT_Error )
3345bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner  Render_Gray_Glyph( RAS_ARG )
3346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED_RASTER;
3348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3349f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_Unsupported;
3350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3352bc82f1bbefa90c649a9ad2c28938d55b4acbf380David Turner#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
3353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
335552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
33568a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_init( PRaster  raster )
3357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
335938d1002b8ab6057a54d3483bc0a6f3808d44794dDavid Turner    FT_UInt  n;
3360a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33614ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg
3362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* set default 5-levels gray palette */
3363a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    for ( n = 0; n < 5; n++ )
3364a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      raster->grays[n] = n * 255 / 4;
3365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33668a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    raster->gray_width = RASTER_GRAY_LINES / 2;
3367eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg#else
3368eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg    FT_UNUSED( raster );
3369a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3370a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3371a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /****                         a static object.                  *****/
3375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef _STANDALONE_
3378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
338052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
3381174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_new( void*       memory,
338252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                FT_Raster  *araster )
3383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
33848a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner     static TRaster  the_raster;
3385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3387f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg     *araster = (FT_Raster)&the_raster;
3388b3d5e9cf03dce78e606b79c81cb1f29ce06555d5Werner Lemberg     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
3389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     ft_black_init( &the_raster );
3390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     return 0;
3392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
339552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
339652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  ft_black_done( FT_Raster  raster )
3397a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing */
3399f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED( raster );
3400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3403a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else /* _STANDALONE_ */
3404a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
340652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
34078a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_new( FT_Memory   memory,
34088a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner                PRaster    *araster )
3409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
34108a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    FT_Error  error;
34118a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    PRaster   raster;
3412a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *araster = 0;
3415e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    if ( !FT_NEW( raster ) )
3416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      raster->memory = memory;
3418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ft_black_init( raster );
3419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *araster = raster;
3421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3422a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3423a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return error;
3424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
342752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
34288a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_done( PRaster  raster )
3429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Memory  memory = (FT_Memory)raster->memory;
3431e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    FT_FREE( raster );
3432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif /* _STANDALONE_ */
3436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
343852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
3439174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_reset( PRaster  raster,
3440174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                  char*    pool_base,
3441174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                  long     pool_size )
3442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
34438a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    if ( raster )
3444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
34458a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )
34468a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      {
34478a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        PWorker  worker = (PWorker)pool_base;
34488a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
34494ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg
34504ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg        raster->buffer      = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );
34514ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg        raster->buffer_size = ( ( pool_base + pool_size ) -
34524ea0a7f0b65c026420f39cabdc146b943c74e2c5Werner Lemberg                                (char*)raster->buffer ) / sizeof ( Long );
34538a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->worker      = worker;
34548a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      }
34558a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      else
34568a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      {
34578a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->buffer      = NULL;
34588a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->buffer_size = 0;
34598a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner        raster->worker      = NULL;
34608a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      }
3461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
346552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
3466174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_set_mode( PRaster        raster,
3467174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                     unsigned long  mode,
3468174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                     const char*    palette )
3469a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3470a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
3471a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
3473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* set 5-levels gray palette */
34758a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[0] = palette[0];
34768a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[1] = palette[1];
34778a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[2] = palette[2];
34788a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[3] = palette[3];
34798a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner      raster->grays[4] = palette[4];
3480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3482a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#else
3483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( raster );
3485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( mode );
3486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( palette );
3487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
3489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
349252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
34938a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  ft_black_render( PRaster                  raster,
3494fa420250c59414e432243feffb70be68654b8c27Werner Lemberg                   const FT_Raster_Params*  params )
3495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
34968ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Outline*  outline    = (const FT_Outline*)params->source;
34978ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Bitmap*   target_map = params->target;
34988a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    PWorker            worker;
3499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35018a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    if ( !raster || !raster->buffer || !raster->buffer_size )
3502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Not_Ini;
3503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35041ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline )
35051ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg      return Raster_Err_Invalid;
35061ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg
3507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* return immediately if the outline is empty */
3508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( outline->n_points == 0 || outline->n_contours <= 0 )
3509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_None;
3510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35111ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline->contours || !outline->points )
3512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Invalid;
3513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3514c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( outline->n_points !=
3515c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg           outline->contours[outline->n_contours - 1] + 1 )
3516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Invalid;
3517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35188a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner    worker = raster->worker;
35198a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
3520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* this version of the raster does not support direct rendering, sorry */
3521b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( params->flags & FT_RASTER_FLAG_DIRECT )
3522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_Unsupported;
3523a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3524c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map )
3525c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg      return Raster_Err_Invalid;
3526c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3527c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    /* nothing to do */
3528c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->width || !target_map->rows )
3529c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg      return Raster_Err_None;
3530c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3531c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->buffer )
35321eb9a43aa14e02b56d981bae334e6e24c63298f7David Turner      return Raster_Err_Invalid;
35331eb9a43aa14e02b56d981bae334e6e24c63298f7David Turner
35345df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.outline = *outline;
35355df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.target  = *target_map;
3536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35375df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->buff       = (PLong) raster->buffer;
35385df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->sizeBuff   = worker->buff +
35395df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg                           raster->buffer_size / sizeof ( Long );
35408a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#ifdef FT_RASTER_OPTION_ANTI_ALIASING
35415df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->grays      = raster->grays;
35425df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    worker->gray_width = raster->gray_width;
3543766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg
3544766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg    FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
35458a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#endif
35468a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
3547cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    return ( params->flags & FT_RASTER_FLAG_AA )
3548cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg           ? Render_Gray_Glyph( RAS_VAR )
3549cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg           : Render_Glyph( RAS_VAR );
3550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
35530d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg  FT_DEFINE_RASTER_FUNCS( ft_standard_raster,
3554b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    FT_GLYPH_FORMAT_OUTLINE,
3555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_New_Func)     ft_black_new,
3556a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Reset_Func)   ft_black_reset,
3557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
3558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Render_Func)  ft_black_render,
3559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    (FT_Raster_Done_Func)    ft_black_done
3560056095096fdce9084e23116f7825784a2ad5e677Oran Agra  )
3561a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/* END */
3564