1a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/***************************************************************************/
2a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
3a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*  ftraster.c                                                             */
4a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
5a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*    The FreeType glyph rasterizer (body).                                */
6a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/*                                                                         */
70a0c22569deab933df21127e75db5c81f724f292Werner Lemberg/*  Copyright 1996-2018 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 */
219d0b76d7f6e87b68ee739688be693f28094b23bfWerner 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  /*                                                                       */
27392cf22f8a5a281b8ebc56bf932e66da78f66410Werner Lemberg  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
28392cf22f8a5a281b8ebc56bf932e66da78f66410Werner Lemberg  /*   current directory                                                   */
29f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
309d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg  /* - compile `ftraster' with the STANDALONE_ macro defined, as in        */
31f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg  /*                                                                       */
329d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg  /*     cc -c -DSTANDALONE_ 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
509d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#ifdef STANDALONE_
51f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
524d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg  /* The size in bytes of the render pool used by the scan-line converter  */
534d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg  /* to do all of its work.                                                */
544d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg#define FT_RENDER_POOL_SIZE  16384L
554d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg
560d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define FT_CONFIG_STANDARD_LIBRARY_H  <stdlib.h>
570d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
58766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg#include <string.h>           /* for memset */
590d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
60f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftmisc.h"
61f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#include "ftimage.h"
62f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
639d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#else /* !STANDALONE_ */
64a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
6519ed8afe60bbc5becf0fbbe3987a91b35a36aad4David Turner#include <ft2build.h>
668d3a401fa808a8c70bd6a9ce17d5a840fb0ae2dbDavid Turner#include "ftraster.h"
67495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg#include FT_INTERNAL_CALC_H   /* for FT_MulDiv and FT_MulDiv_No_Round */
68a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
690d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#include "rastpic.h"
700d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
719d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#endif /* !STANDALONE_ */
72f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg
73a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
74a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
75a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
76a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A simple technical note on how the raster works                       */
77a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* -----------------------------------------------                       */
78a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
79a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Converting an outline into a bitmap is achieved in several steps:   */
80a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
81a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
82a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       profile is simply an array of scanline intersections on a given */
83a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       dimension.  A profile's main attributes are                     */
84a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
858262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'      */
86a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
87a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o an array of intersection coordinates for each scanline        */
888262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*         between `Ymin' and `Ymax'                                     */
89a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
90a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       o a direction, indicating whether it was built going `up' or    */
918262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*         `down', as this is very important for filling rules           */
928262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*                                                                       */
938262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*       o its drop-out mode                                             */
94a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
95a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   2 - Sweeping the target map's scanlines in order to compute segment */
96a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       `spans' which are then filled.  Additionally, this pass         */
97a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*       performs drop-out control.                                      */
98a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
99a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The outline data is parsed during step 1 only.  The profiles are    */
100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the bottom of the render pool, used as a stack.  The     */
101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   following graphics shows the profile list under construction:       */
102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1038262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*     __________________________________________________________ _ _    */
1048262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |         |                 |         |                 |          */
1058262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    | profile | coordinates for | profile | coordinates for |-->       */
1068262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |    1    |  profile 1      |    2    |  profile 2      |-->       */
1078262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |_________|_________________|_________|_________________|__ _ _    */
108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1098262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    ^                                                       ^          */
1108262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /*    |                                                       |          */
1118262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* start of render pool                                      top         */
112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   The top of the profile stack is kept in the `top' variable.         */
114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   As you can see, a profile record is pushed on top of the render     */
116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   pool, which is then followed by its coordinates/intersections.  If  */
117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   a change of direction is detected in the outline, a new profile is  */
118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   generated until the end of the outline.                             */
119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Note that when all profiles have been generated, the function       */
121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   bottom-most scanline as well as the scanline above its upmost       */
123a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   boundary.  These positions are called `y-turns' because they (sort  */
124a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   of) correspond to local extrema.  They are stored in a sorted list  */
125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   built from the top of the render pool as a downwards stack:         */
126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ _______________________________________                      */
128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--| sorted list of     |                     */
130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         <--|  extrema scanlines |                     */
131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*      _ _ __________________|____________________|                     */
132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            ^                    ^                     */
134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                            |                    |                     */
135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                         maxBuff           sizeBuff = end of pool      */
136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   This list is later used during the sweep phase in order to          */
138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   optimize performance (see technical note on the sweep below).       */
139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   Of course, the raster detects whether the two stacks collide and    */
1416e87ed9f04f7914e15f9284b0b762b730222c399Werner Lemberg  /*   handles the situation properly.                                     */
142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  CONFIGURATION MACROS                                               **/
150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* define DEBUG_RASTER if you want to compile a debugging version */
155766b822f4c1cc84cc11545b63be87108d0954b48Werner Lemberg/* #define DEBUG_RASTER */
156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  OTHER MACROS (do not change)                                       **/
162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* messages during execution.                                            */
171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  FT_COMPONENT
173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_COMPONENT  trace_raster
174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1769d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#ifdef STANDALONE_
177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
178059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg  /* Auxiliary macros for token concatenation. */
179059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#define FT_ERR_XCAT( x, y )  x ## y
180059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* This macro is used to indicate that a function parameter is unused. */
183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* ANSI compilers (e.g. LCC).                                          */
186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FT_UNUSED( x )  (x) = (x)
187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Disable the tracing mechanism for simplicity -- developers can      */
189059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg  /* activate it easily by redefining these macros.                      */
190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_ERROR
191f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_ERROR( x )  do { } while ( 0 )     /* nothing */
192a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
193a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FT_TRACE
195f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE( x )   do { } while ( 0 )    /* nothing */
196f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE1( x )  do { } while ( 0 )    /* nothing */
197f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_TRACE6( x )  do { } while ( 0 )    /* nothing */
198d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg#define FT_TRACE7( x )  do { } while ( 0 )    /* nothing */
199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
201059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#ifndef FT_THROW
202059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#define FT_THROW( e )  FT_ERR_CAT( Raster_Err_, e )
203059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#endif
204059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg
205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_None          0
206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Not_Ini      -1
207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Overflow     -2
208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Neg_Height   -3
209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Invalid      -4
210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Raster_Err_Unsupported  -5
211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2120d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define ft_memset  memset
2130d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg
2140d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
2150d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg                                raster_reset_, raster_set_mode_,    \
2160d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg                                raster_render_, raster_done_ )      \
2170d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg          const FT_Raster_Funcs class_ =                            \
2180d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg          {                                                         \
2190d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            glyph_format_,                                          \
2200d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_new_,                                            \
2210d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_reset_,                                          \
2220d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_set_mode_,                                       \
2230d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_render_,                                         \
2240d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg            raster_done_                                            \
2250d02317fb2a6f46e568cefc1132273cdd1bc80b7Werner Lemberg         };
2268262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg
2279d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#else /* !STANDALONE_ */
228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2301f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include FT_INTERNAL_OBJECTS_H
231059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg#include FT_INTERNAL_DEBUG_H       /* for FT_TRACE, FT_ERROR, and FT_THROW */
232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2331f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#include "rasterrs.h"
2341f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg
235e3c9301581a450fae5db73a3b94b10ed6a0aeb5eWerner Lemberg#define Raster_Err_None         FT_Err_Ok
2361f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
2371f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
2381f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
2391f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
2401f7f0e87e58168b2e739e2622db0ee06e0c9acccWerner Lemberg#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2439d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#endif /* !STANDALONE_ */
244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
246e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner#ifndef FT_MEM_SET
247d15bc0d13a163995e1ca11925349bd64d1c33617David Turner#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
248c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg#endif
249c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
250f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifndef FT_MEM_ZERO
251f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
252f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#endif
253c3b21608699a72698d382ad44c5f9fd6946ce43cWerner Lemberg
25445cad2e5e15c08b682e87b5636cccfc941b3fe7dWerner Lemberg#ifndef FT_ZERO
25545cad2e5e15c08b682e87b5636cccfc941b3fe7dWerner Lemberg#define FT_ZERO( p )  FT_MEM_ZERO( p, sizeof ( *(p) ) )
25645cad2e5e15c08b682e87b5636cccfc941b3fe7dWerner Lemberg#endif
25745cad2e5e15c08b682e87b5636cccfc941b3fe7dWerner Lemberg
258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* typically a small value and the result of a*b is known to fit into */
260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* 32 bits.                                                           */
261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* defined in `ftcalc.h'.                                                */
266495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg#define SMulDiv           FT_MulDiv
267495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg#define SMulDiv_No_Round  FT_MulDiv_No_Round
268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* The rasterizer is a very general purpose component; please leave */
270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* the following redefinitions there (you never know your target    */
271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* environment).                                                    */
272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef TRUE
274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define TRUE   1
275a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FALSE
278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FALSE  0
279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef NULL
282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define NULL  (void*)0
283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef SUCCESS
286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SUCCESS  0
287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifndef FAILURE
290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FAILURE  1
291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
292a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* Setting this constant to more than 32 is a   */
296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                        /* pure waste of space.                         */
297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SIMPLE TYPE DECLARATIONS                                           **/
305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
307a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef int             Int;
310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned int    UInt;
311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef short           Short;
312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned short  UShort, *PUShort;
313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef long            Long, *PLong;
314073a0e2901e931d457f205d870ee77eb0ed763cbWerner Lemberg  typedef unsigned long   ULong;
315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef unsigned char   Byte, *PByte;
317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef char            Bool;
318a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
319fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
320fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg  typedef union  Alignment_
3218530a228889128adfd446514928f36663ed20f04David Turner  {
322a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    Long    l;
3238530a228889128adfd446514928f36663ed20f04David Turner    void*   p;
3248530a228889128adfd446514928f36663ed20f04David Turner    void  (*f)(void);
3258530a228889128adfd446514928f36663ed20f04David Turner
3268530a228889128adfd446514928f36663ed20f04David Turner  } Alignment, *PAlignment;
3278530a228889128adfd446514928f36663ed20f04David Turner
328fefd8742928491a9da356cc1c37f434c76d73514Werner Lemberg
329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct  TPoint_
330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  x;
332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  y;
333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TPoint;
335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
33742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /* values for the `flags' bit field */
338ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg#define Flow_Up           0x08U
339ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg#define Overshoot_Top     0x10U
340ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg#define Overshoot_Bottom  0x20U
341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* States of each line, arc, and profile */
344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef enum  TStates_
345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3469ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Unknown_State,
3479ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Ascending_State,
3489ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Descending_State,
3499ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    Flat_State
350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  } TStates;
352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef struct TProfile_  TProfile;
355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef TProfile*         PProfile;
356a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  struct  TProfile_
358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
35942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    FT_F26Dot6  X;           /* current coordinate during sweep          */
36042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PProfile    link;        /* link to next profile (various purposes)  */
36142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PLong       offset;      /* start of profile's data in render pool   */
362ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg    UShort      flags;       /* Bit 0-2: drop-out mode                   */
36372271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 3: profile orientation (up/down)     */
36472271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 4: is top profile?                   */
36572271140434028186a49a5dc5925f0727559e46fWerner Lemberg                             /* Bit 5: is bottom profile?                */
366a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    Long        height;      /* profile's height in scanlines            */
367a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    Long        start;       /* profile's starting scanline              */
36842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
369ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg    Int         countL;      /* number of lines to step before this      */
37042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             /* profile becomes drawable                 */
37142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
37242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    PProfile    next;        /* next profile in same contour, used       */
37342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             /* during drop-out control                  */
374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  };
375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile   TProfileList;
377a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef PProfile*  PProfileList;
378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
380a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* Simple record used to implement a stack of bands, required */
381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* by the sub-banding mechanism                               */
382126405adde4caf69ea6eacf478ce805f6635f42aVinnie Falco  typedef struct  black_TBand_
383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_min;   /* band's minimum */
385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  y_max;   /* band's maximum */
386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
387126405adde4caf69ea6eacf478ce805f6635f42aVinnie Falco  } black_TBand;
388a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define AlignProfileSize \
391a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
393a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
39495111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco#undef RAS_ARG
39595111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco#undef RAS_ARGS
39695111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco#undef RAS_VAR
39795111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco#undef RAS_VARS
39895111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco
399f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARGS       /* void */
403a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_ARG        /* void */
404a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VARS       /* void */
406a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define RAS_VAR        /* void */
407a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
408f47acf2b5fcd9d6c9dc58809ef8ecf1b1e0b46adWerner Lemberg#define FT_UNUSED_RASTER  do { } while ( 0 )
409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4118262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#else /* !FT_STATIC_RASTER */
412a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
414d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco#define RAS_ARGS       black_PWorker  worker,
415d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco#define RAS_ARG        black_PWorker  worker
416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4178a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VARS       worker,
4188a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define RAS_VAR        worker
419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4208a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define FT_UNUSED_RASTER  FT_UNUSED( worker )
421a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
422a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4238262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#endif /* !FT_STATIC_RASTER */
424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
426d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco  typedef struct black_TWorker_  black_TWorker, *black_PWorker;
427a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* prototypes used for sweep function dispatch */
43052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
43152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Init( RAS_ARGS Short*  min,
43252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max );
433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
43452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
43552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Span( RAS_ARGS Short       y,
43652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
43752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
43852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
43952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right );
440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
44152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  typedef void
44252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Function_Sweep_Step( RAS_ARG );
443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* NOTE: These operations are only valid on 2's complement processors */
4465ccebc4e1eb71e5ee82a88edb9cd553e08fc69b9Vinnie Falco#undef FLOOR
4475ccebc4e1eb71e5ee82a88edb9cd553e08fc69b9Vinnie Falco#undef CEILING
4485ccebc4e1eb71e5ee82a88edb9cd553e08fc69b9Vinnie Falco#undef TRUNC
4495ccebc4e1eb71e5ee82a88edb9cd553e08fc69b9Vinnie Falco#undef SCALED
450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FLOOR( x )    ( (x) & -ras.precision )
452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
453073a0e2901e931d457f205d870ee77eb0ed763cbWerner Lemberg#define TRUNC( x )    ( (Long)(x) >> ras.precision_bits )
454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
4556343ba22a36ab264fa061cab3b87662d5b7b7114Werner Lemberg#define SCALED( x )   ( ( (x) < 0 ? -( -(x) << ras.scale_shift )   \
4566343ba22a36ab264fa061cab3b87662d5b7b7114Werner Lemberg                                  :  (  (x) << ras.scale_shift ) ) \
4576343ba22a36ab264fa061cab3b87662d5b7b7114Werner Lemberg                        - ras.precision_half )
458a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
459c06889eb2c42b40d9ef557b03c9b57d6057e0f12Werner Lemberg#define IS_BOTTOM_OVERSHOOT( x ) \
460c06889eb2c42b40d9ef557b03c9b57d6057e0f12Werner Lemberg          (Bool)( CEILING( x ) - x >= ras.precision_half )
461c06889eb2c42b40d9ef557b03c9b57d6057e0f12Werner Lemberg#define IS_TOP_OVERSHOOT( x )    \
462c06889eb2c42b40d9ef557b03c9b57d6057e0f12Werner Lemberg          (Bool)( x - FLOOR( x ) >= ras.precision_half )
46342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
46472a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)#if FT_RENDER_POOL_SIZE > 2048
46572a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)#define FT_MAX_BLACK_POOL  ( FT_RENDER_POOL_SIZE / sizeof ( Long ) )
4663e1f7bc506652bbeb89632733430a72a92dde2cdAlexei Podtelezhnikov (Алексей Подтележников)#else
46772a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)#define FT_MAX_BLACK_POOL  ( 2048 / sizeof ( Long ) )
46872a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)#endif
46972a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)
4708262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* The most used variables are positioned at the top of the structure. */
4718262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* Thus, their offset can be coded with less opcodes, resulting in a   */
4728262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg  /* smaller executable.                                                 */
473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
474d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco  struct  black_TWorker_
475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
4768262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_bits;     /* precision related variables         */
4778262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision;
4788262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_half;
4798262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_shift;
4808262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_step;
4818262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         precision_jitter;
4828262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg
4838262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         scale_shift;        /* == precision_shift   for bitmaps    */
484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* == precision_shift+1 for pixmaps    */
485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4868262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       buff;               /* The profiles buffer                 */
4878262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       sizeBuff;           /* Render pool size                    */
4888262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       maxBuff;            /* Profiles buffer size                */
4898262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PLong       top;                /* Current cursor in buffer            */
490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4918262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    FT_Error    error;
492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4938262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Int         numTurns;           /* number of Y-turns in outline        */
494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4958262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TPoint*     arc;                /* current Bezier arc pointer          */
496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
4978262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    UShort      bWidth;             /* target bitmap width                 */
4988262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PByte       bTarget;            /* target bitmap buffer                */
4998262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PByte       gTarget;            /* target pixmap buffer                */
500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5018262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        lastX, lastY;
5028262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        minY, maxY;
503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5048262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    UShort      num_Profs;          /* current number of profiles          */
505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5068262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        fresh;              /* signals a fresh new profile which   */
50790c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg                                    /* `start' field must be completed     */
5088262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        joint;              /* signals that the last arc ended     */
509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* exactly on a scanline.  Allows      */
510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* removal of doublets                 */
5118262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    cProfile;           /* current profile                     */
5128262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    fProfile;           /* head of linked list of profiles     */
5138262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    PProfile    gProfile;           /* contour's first profile in case     */
514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* of impact                           */
515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5168262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TStates     state;              /* rendering state                     */
517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Bitmap   target;             /* description of target bit/pixmap    */
519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Outline  outline;
520a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5218262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        traceOfs;           /* current offset in target bitmap     */
5228262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Long        traceG;             /* current offset in target pixmap     */
523a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5248262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Short       traceIncr;          /* sweep's increment in target bitmap  */
525a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
526a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* dispatch variables */
527a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Init*  Proc_Sweep_Init;
529a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Span;
530a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Span*  Proc_Sweep_Drop;
531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Function_Sweep_Step*  Proc_Sweep_Step;
532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5338262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Byte        dropOutControl;     /* current drop_out control method     */
534a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5358262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    Bool        second_pass;        /* indicates whether a horizontal pass */
536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* should be performed to control      */
537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                    /* drop-out accurately when calling    */
5388dc863587440d0a1d2eec2a7973a8eda99d2767dBehdad Esfahbod                                    /* Render_Glyph.                       */
539a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5408262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg    TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
542126405adde4caf69ea6eacf478ce805f6635f42aVinnie Falco    black_TBand  band_stack[16];    /* band stack used for sub-banding     */
543126405adde4caf69ea6eacf478ce805f6635f42aVinnie Falco    Int          band_top;          /* band stack top                      */
544a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5458a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  };
546a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
54895111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco  typedef struct  black_TRaster_
5498a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner  {
550d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco    void*          memory;
551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
55295111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco  } black_TRaster, *black_PRaster;
553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
554f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg#ifdef FT_STATIC_RASTER
555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
556d55f16df11121ef4d5af8dfa0d7670d0bb0e238fVinnie Falco  static black_TWorker  cur_ras;
557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define ras  cur_ras
558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5598262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#else /* !FT_STATIC_RASTER */
560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5618a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner#define ras  (*worker)
562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
5638262213192704679677edfd6f1b89c94b8de8f3bWerner Lemberg#endif /* !FT_STATIC_RASTER */
564a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
565a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
566a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
567a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
568a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
569a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  PROFILES COMPUTATION                                               **/
570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
574a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Set_High_Precision                                                 */
579a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
581174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Set precision variables according to param flag.                   */
582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
584762bf19ab7416a40c8c3cf553bd4f02eec45c3b2Werner Lemberg  /*    High :: Set to True for high precision (typically for ppem < 24),  */
585a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*            false otherwise.                                           */
586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
58752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
58852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Set_High_Precision( RAS_ARGS Int  High )
589a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
590c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg    /*
591c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * `precision_step' is used in `Bezier_Up' to decide when to split a
592c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * given y-monotonous Bezier arc that crosses a scanline before
593c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * approximating it as a straight segment.  The default value of 32 (for
594c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * low accuracy) corresponds to
595c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
596d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg     *   32 / 64 == 0.5 pixels,
597c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
598c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * while for the high accuracy case we have
599c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
600d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg     *   256 / (1 << 12) = 0.0625 pixels.
601c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
602c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * `precision_jitter' is an epsilon threshold used in
603c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
604c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * decomposition (after all, we are working with approximations only);
605c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * it avoids switching on additional pixels which would cause artifacts
606c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * otherwise.
607c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
608c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     * The value of `precision_jitter' has been determined heuristically.
609c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     *
610c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg     */
611c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg
612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( High )
613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
6140409ef32686188c1947298e0fca9fbeadd23c1c3Werner Lemberg      ras.precision_bits   = 12;
6150409ef32686188c1947298e0fca9fbeadd23c1c3Werner Lemberg      ras.precision_step   = 256;
616c02485cb725f94ea0487351596adc1e3ef8d1ae6Werner Lemberg      ras.precision_jitter = 30;
617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_bits   = 6;
621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_step   = 32;
622a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.precision_jitter = 2;
623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
62768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg    ras.precision       = 1 << ras.precision_bits;
628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_half  = ras.precision / 2;
629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.precision_shift = ras.precision_bits - Pixel_Bits;
630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
631a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
632a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New_Profile                                                        */
637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
639174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Create a new profile in the render pool.                           */
640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
64242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    aState    :: The state/orientation of the new profile.             */
64342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                                                                       */
64442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    overshoot :: Whether the profile's unrounded start position        */
64542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                 differs by at least a half pixel.                     */
646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
65152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
65242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  New_Profile( RAS_ARGS TStates  aState,
65342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                        Bool     overshoot )
654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.fProfile )
656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile  = (PProfile)ras.top;
658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile  = ras.cProfile;
659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top      += AlignProfileSize;
660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
662a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
664059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Overflow );
665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
666a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
66842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->flags  = 0;
66942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->start  = 0;
67042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->height = 0;
67142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->offset = ras.top;
67242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->link   = (PProfile)0;
67342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg    ras.cProfile->next   = (PProfile)0;
67472271140434028186a49a5dc5925f0727559e46fWerner Lemberg    ras.cProfile->flags  = ras.dropOutControl;
67542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( aState )
677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
6789ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
67990c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg      ras.cProfile->flags |= Flow_Up;
68042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
68142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        ras.cProfile->flags |= Overshoot_Bottom;
68242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
683d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE6(( "  new ascending profile = %p\n", ras.cProfile ));
684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
6869ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
68742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
68842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        ras.cProfile->flags |= Overshoot_Top;
689d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE6(( "  new descending profile = %p\n", ras.cProfile ));
690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
693858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "New_Profile: invalid profile direction\n" ));
694059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Invalid );
695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !ras.gProfile )
699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = ras.cProfile;
700a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.state = aState;
702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh = TRUE;
703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    End_Profile                                                        */
713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
714a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
715174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Finalize the current profile.                                      */
716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
71742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /* <Input>                                                               */
71842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*    overshoot :: Whether the profile's unrounded end position differs  */
71942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                 by at least a half pixel.                             */
72042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  /*                                                                       */
721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
72452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
72542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg  End_Profile( RAS_ARGS Bool  overshoot )
726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
727dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg    Long  h;
728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
729a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
730914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg    h = (Long)( ras.top - ras.cProfile->offset );
731a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h < 0 )
733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
734858abbedc0c156965aba830bfc2072a3c21144cfWerner Lemberg      FT_ERROR(( "End_Profile: negative height encountered\n" ));
735059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Neg_Height );
736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( h > 0 )
740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
741dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg      PProfile  oldProfile;
742dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
743dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
744d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
74546c371c2c7398d25fa614065c28a27ebb4b5d489Suzuki, Toshiya (鈴木俊哉)                  ras.cProfile, ras.cProfile->start, h ));
746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = h;
74842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( overshoot )
74942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      {
75042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( ras.cProfile->flags & Flow_Up )
75142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          ras.cProfile->flags |= Overshoot_Top;
75242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        else
75342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          ras.cProfile->flags |= Overshoot_Bottom;
75442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      }
755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
75642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      oldProfile   = ras.cProfile;
75742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      ras.cProfile = (PProfile)ras.top;
75842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
75942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      ras.top += AlignProfileSize;
760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->height = 0;
762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->offset = ras.top;
76342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
76442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      oldProfile->next = ras.cProfile;
765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.num_Profs++;
766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top >= ras.maxBuff )
769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
770a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      FT_TRACE1(( "overflow in End_Profile\n" ));
771059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Overflow );
772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint = FALSE;
776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
779a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
780a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
783a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Insert_Y_Turn                                                      */
785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
787174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Insert a salient into the sorted list placed on top of the render  */
788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    pool.                                                              */
789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    New y scanline position.                                           */
792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
79652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
79752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Insert_Y_Turn( RAS_ARGS Int  y )
798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
79951daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg    PLong  y_turns;
800dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg    Int    n;
801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n       = ras.numTurns - 1;
804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_turns = ras.sizeBuff - ras.numTurns;
805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* look for first y value that is <= */
807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( n >= 0 && y < y_turns[n] )
808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      n--;
809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* if it is <, simply insert it, ignore if == */
811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n >= 0 && y > y_turns[n] )
8125a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)      do
813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
814dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg        Int  y2 = (Int)y_turns[n];
815dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
816dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y_turns[n] = y;
818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y = y2;
8195a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)      } while ( --n >= 0 );
820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( n < 0 )
822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
82351daa4feb18fce52a3c5d40bd6c9969203ec6b28Werner Lemberg      ras.maxBuff--;
824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.maxBuff <= ras.top )
825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
826059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg        ras.error = FT_THROW( Overflow );
827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns++;
830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.sizeBuff[-ras.numTurns] = y;
831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Finalize_Profile_Table                                             */
841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
843174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Adjust all links in the profiles list.                             */
844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
84852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
84952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Finalize_Profile_Table( RAS_ARG )
850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    UShort    n;
852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  p;
853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    n = ras.num_Profs;
856b66efefdcde552e4880896aa961a0b9a583762d2Werner Lemberg    p = ras.fProfile;
857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
858b66efefdcde552e4880896aa961a0b9a583762d2Werner Lemberg    if ( n > 1 && p )
859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
8605a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)      do
861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
862dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg        Int  bottom, top;
863dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
864dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( n > 1 )
866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = (PProfile)( p->offset + p->height );
867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->link = NULL;
869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
87090c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        if ( p->flags & Flow_Up )
87190c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        {
87290c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          bottom = (Int)p->start;
87390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          top    = (Int)( p->start + p->height - 1 );
87490c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        }
87590c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        else
876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
87768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          bottom     = (Int)( p->start - p->height + 1 );
87868e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg          top        = (Int)p->start;
879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->start   = bottom;
880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p->offset += p->height - 1;
881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
88390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
88490c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg             Insert_Y_Turn( RAS_VARS top + 1 ) )
885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        p = p->link;
8885a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)      } while ( --n );
889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fProfile = NULL;
892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Conic                                                        */
901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
903174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide one conic Bezier into two joint sub-arcs in the Bezier   */
904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    stack.                                                             */
905a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
906a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    None (subdivided Bezier is taken from the top of the stack).       */
908a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    loop that should be optimized to hell to get the best performance. */
912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
91352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
91452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Conic( TPoint*  base )
915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b;
917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = base[2].x;
920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x;
921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].x = ( base[2].x + b ) / 2;
922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].x = ( base[0].x + b ) / 2;
923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = ( a + b ) / 2;
924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = base[2].y;
926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y;
927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    a = base[3].y = ( base[2].y + b ) / 2;
928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    b = base[1].y = ( base[0].y + b ) / 2;
929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = ( a + b ) / 2;
930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* hand optimized.  gcc doesn't seem to be too good at common      */
932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* expression substitution and instruction scheduling ;-)          */
933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Split_Cubic                                                        */
940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
942174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Subdivide a third-order Bezier arc into two joint sub-arcs in the  */
943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier stack.                                                      */
944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Note>                                                                */
946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    This routine is the `beef' of the component.  It is one of _the_   */
947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    inner loops that should be optimized like hell to get the best     */
948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    performance.                                                       */
949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
95052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
95152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Split_Cubic( TPoint*  base )
952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  a, b, c, d;
954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].x = base[3].x;
957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].x;
958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].x;
959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].x = a = ( a + c + 1 ) >> 1;
963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].x = b = ( b + c + 1 ) >> 1;
964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].x = ( a + b + 1 ) >> 1;
965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[6].y = base[3].y;
967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = base[1].y;
968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    d = base[2].y;
969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    c = ( c + d + 1 ) >> 1;
972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[2].y = a = ( a + c + 1 ) >> 1;
973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[4].y = b = ( b + c + 1 ) >> 1;
974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    base[3].y = ( a + b + 1 ) >> 1;
975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
977a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
978a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Up                                                            */
982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
984174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending line segment and store   */
985a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
988a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
990a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
992a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
994a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
995a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
996a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
100352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
100452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Up( RAS_ARGS Long  x1,
100552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y1,
100652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  x2,
100752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y2,
100852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  miny,
100952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  maxy )
1010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Dx, Dy;
1012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
1013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   Ix, Rx, Ax;
1014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong  top;
1016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dx = x2 - x1;
1019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Dy = y2 - y1;
1020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dy <= 0 || y2 < miny || y1 > maxy )
1022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return SUCCESS;
1023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
1025a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* Take care: miny-y1 can be a very large value; we use     */
1027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /*            a slow MulDiv function to avoid clipping bugs */
1028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += SMulDiv( Dx, miny - y1, Dy );
102973861976779a754cc9b808760cc8e6cf98d52549Werner Lemberg      e1  = (Int)TRUNC( miny );
1030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f1  = 0;
1031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
103468e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e1 = (Int)TRUNC( y1 );
103568e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f1 = (Int)FRAC( y1 );
1036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 > maxy )
1039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
104168e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2  = (Int)TRUNC( maxy );
1042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      f2  = 0;
1043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
104668e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      e2 = (Int)TRUNC( y2 );
104768e9f927105b22ec6952a5bc929cfabfc6b7e810Werner Lemberg      f2 = (Int)FRAC( y2 );
1048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( f1 > 0 )
1051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
1053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return SUCCESS;
1054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1056f0987abdc24b136100656f49ecfe3997869cd93dWerner Lemberg        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
1057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 += 1;
1058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.joint )
1062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.top--;
1064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.joint = FALSE;
1065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
10678edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    ras.joint = (char)( f2 == 0 );
1068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = e1;
1072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh           = FALSE;
1073a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    size = e2 - e1 + 1;
1076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.top + size >= ras.maxBuff )
1077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1078059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Overflow );
1079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1081a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1082a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Dx > 0 )
1083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1084495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
1085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Rx = ( ras.precision * Dx ) % Dy;
1086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = 1;
1087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1088a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1090495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
1091495bd3cc4f54f5f4604709391a716fcd0c033277Werner Lemberg      Rx = ( ras.precision * -Dx ) % Dy;
1092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Dx = -1;
1093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Ax  = -Dy;
1096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( size > 0 )
1099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *top++ = x1;
1101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x1 += Ix;
1103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Ax += Rx;
1104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Ax >= 0 )
1105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Ax -= Dy;
1107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        x1 += Dx;
1108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      size--;
1110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top = top;
1113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_Down                                                          */
1121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1123174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending line segment and store  */
1124174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    them in the render pool.                                           */
1125a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x1   :: The x-coordinate of the segment's start point.             */
1128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1129a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y1   :: The y-coordinate of the segment's start point.             */
1130a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    x2   :: The x-coordinate of the segment's end point.               */
1132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    y2   :: The y-coordinate of the segment's end point.               */
1134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny :: A lower vertical clipping bound value.                     */
1136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy :: An upper vertical clipping bound value.                    */
1138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
114252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
114352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_Down( RAS_ARGS Long  x1,
114452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y1,
114552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  x2,
114652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  y2,
114752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  miny,
114852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long  maxy )
1149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool  result, fresh;
1151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh  = ras.fresh;
1154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* A function type describing the functions used to split Bezier arcs */
1165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  typedef void  (*TSplitter)( TPoint*  base );
1166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Up                                                          */
1172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1174174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an ascending Bezier arc and store     */
1175a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1176a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1177a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1187a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
118952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
119052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Up( RAS_ARGS Int        degree,
119152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      TSplitter  splitter,
119252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       miny,
119352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                      Long       maxy )
1194a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1195a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   y1, y2, e, e2, e0;
1196a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  f1;
1197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc;
1199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  start_arc;
1200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1201a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PLong top;
1202a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc = ras.arc;
1205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y1  = arc[degree].y;
1206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y2  = arc[0].y;
1207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    top = ras.top;
1208a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y2 < miny || y1 > maxy )
1210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1212a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e2 = FLOOR( y2 );
1213a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1214a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 > maxy )
1215a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = maxy;
1216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e0 = miny;
1218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( y1 < miny )
1220a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e = miny;
1221a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
1222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e  = CEILING( y1 );
1224914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( FRAC( y1 ) );
1225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e0 = e;
1226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( f1 == 0 )
1228a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1229a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.joint )
1230a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1231a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          top--;
1232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint = FALSE;
1233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *top++ = arc[degree].x;
1236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1237a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e += ras.precision;
1238a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.fresh )
1242a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1243a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = TRUNC( e0 );
1244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.fresh = FALSE;
1245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 < e )
1248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fin;
1249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1252a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top   = top;
1253059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Overflow );
1254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
1255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start_arc = arc;
1258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
12595a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)    do
1260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.joint = FALSE;
1262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = arc[0].y;
1264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 > e )
1266a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1267a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y1 = arc[degree].y;
1268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 - y1 >= ras.precision_step )
1269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          splitter( arc );
1271a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc += degree;
1272a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1273a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1274a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1275cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
1276a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                            e - y1, y2 - y1 );
1277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          arc -= degree;
1278a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e   += ras.precision;
1279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1282a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1283a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y2 == e )
1284a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1285a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.joint  = TRUE;
1286a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *top++     = arc[0].x;
1287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          e += ras.precision;
1289a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1290a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        arc -= degree;
1291a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
12925a6dc87240905f0e55568678e0fbf93a51242051Alexei Podtelezhnikov (Алексей Подтележников)    } while ( arc >= start_arc && e <= e2 );
1293a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1294a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fin:
1295a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.top  = top;
1296a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc -= degree;
1297a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1298a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1299a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1300a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1301a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1302a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1303a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1304a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Bezier_Down                                                        */
1305a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1306a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1307174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Compute the x-coordinates of an descending Bezier arc and store    */
1308a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    them in the render pool.                                           */
1309a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1310a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1311a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
1312a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    splitter :: The function to split Bezier arcs.                     */
1314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    miny     :: A lower vertical clipping bound value.                 */
1316a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1317a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    maxy     :: An upper vertical clipping bound value.                */
1318a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1319a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1320a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
132252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
132352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Bezier_Down( RAS_ARGS Int        degree,
132452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        TSplitter  splitter,
132552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       miny,
132652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                        Long       maxy )
1327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TPoint*  arc = ras.arc;
1329a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Bool     result, fresh;
1330a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1333a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[1].y = -arc[1].y;
1334a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[2].y = -arc[2].y;
1335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( degree > 2 )
1336a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      arc[3].y = -arc[3].y;
1337a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1338a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    fresh = ras.fresh;
1339a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1341a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( fresh && !ras.fresh )
1343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.cProfile->start = -ras.cProfile->start;
1344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    arc[0].y = -arc[0].y;
1346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return result;
1347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1349a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Line_To                                                            */
1354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1355a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1356174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new line segment and adjust the Profiles list.            */
1357a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1358a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1359a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x :: The x-coordinate of the segment's end point (its start point   */
1360ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastX').                                         */
1361a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1362a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y :: The y-coordinate of the segment's end point (its start point   */
1363ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*        is stored in `lastY').                                         */
1364a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1365a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1366a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1367a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
136952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
137052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Line_To( RAS_ARGS Long  x,
137152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                    Long  y )
1372a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1373a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, detect a change of direction */
1374a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1376a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
13779ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Unknown_State:
1378a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1379a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
138042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( New_Profile( RAS_VARS Ascending_State,
138142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1382a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1383a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1384a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1386a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < ras.lastY )
138742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS Descending_State,
138842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
1389a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            return FAILURE;
1390a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1391a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1392a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
13939ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1394a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y < ras.lastY )
1395a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
139642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
139742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             New_Profile( RAS_VARS Descending_State,
139842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
1399a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1400a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1402a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
14039ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1404a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y > ras.lastY )
1405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
140642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
140742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             New_Profile( RAS_VARS Ascending_State,
140842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
1410a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1411a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1412a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1414a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1415a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1417a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then compute the lines */
1418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    switch ( ras.state )
1420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
14219ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Ascending_State:
1422a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
142342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                             x, y, ras.minY, ras.maxY ) )
1424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
14279ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg    case Descending_State:
1428a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
142942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                               x, y, ras.minY, ras.maxY ) )
1430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      break;
1432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    default:
1434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ;
1435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x;
1438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y;
1439a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1443a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1444a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1445a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Conic_To                                                           */
1448a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1449a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1450174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new conic arc and adjust the profile list.                */
1451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx :: The x-coordinate of the arc's new control point.              */
1454a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1455a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy :: The y-coordinate of the arc's new control point.              */
1456a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1457a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
1458ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastX').                                           */
1459a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1460a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
1461ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*         stored in `lastY').                                           */
1462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1466a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
146752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
146852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Conic_To( RAS_ARGS Long  cx,
146952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy,
147052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
147152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1472a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1473a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, x3, ymin, ymax;
1474a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].x = ras.lastX;
1479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[2].y = ras.lastY;
1480cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].x = cx;
1481cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].y = cy;
1482cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].x = x;
1483cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].y = y;
1484a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1485a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[2].y;
1488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[1].y;
1489a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[0].y;
1490a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x3 = ras.arc[0].x;
1491a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1492a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1493a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1494a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y3 )
1495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1496a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y1;
1497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y3;
1498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1501a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin = y3;
1502a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax = y1;
1503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 < ymin || y2 > ymax )
1506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1507a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1508a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Conic( ras.arc );
1509a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 2;
1510a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1511a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y3 )
1512a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1514a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 2;
1515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the arc is y-monotonous, either ascending or descending */
1519a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction                            */
15209ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = y1 < y3 ? Ascending_State : Descending_State;
1521a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1522a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
152337c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg          Bool  o = ( state_bez == Ascending_State )
152437c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg                      ? IS_BOTTOM_OVERSHOOT( y1 )
152537c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg                      : IS_TOP_OVERSHOOT( y1 );
152642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
152742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
1528a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* finalize current profile if any */
1529cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          if ( ras.state != Unknown_State &&
153042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               End_Profile( RAS_VARS o )  )
1531a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1532a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1533a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* create a new profile */
153442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS state_bez, o ) )
1535a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1536a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1537a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1538a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* now call the appropriate routine */
15399ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1542a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1543a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1544a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1545a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1546a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1548a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1549a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1551a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x3;
1552a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y3;
1553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1554a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1555a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1556a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1559a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1560a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1561a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1564a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Cubic_To                                                           */
1565a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1566a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1567174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Inject a new cubic arc and adjust the profile list.                */
1568a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1569a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
1571a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1572a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
1573a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1574a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
1575a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
1577a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1578a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
1579ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastX').                                          */
1580a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1581a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
1582ce235eaf099765b1a868ce27fef4e83171767e11Werner Lemberg  /*          stored in `lastY').                                          */
1583a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1584a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1585a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
1586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*   profile.                                                            */
1587a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
158852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
158952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Cubic_To( RAS_ARGS Long  cx1,
159052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy1,
159152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cx2,
159252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  cy2,
159352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  x,
159452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                     Long  y )
1595a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1596a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TStates  state_bez;
1598a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1600a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc      = ras.arcs;
1601a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].x = ras.lastX;
1602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.arc[3].y = ras.lastY;
1603cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[2].x = cx1;
1604cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[2].y = cy1;
1605cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].x = cx2;
1606cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[1].y = cy2;
1607cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].x = x;
1608cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    ras.arc[0].y = y;
1609a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1610a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    do
1611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y1 = ras.arc[3].y;
1613a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y2 = ras.arc[2].y;
1614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y3 = ras.arc[1].y;
1615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y4 = ras.arc[0].y;
1616a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      x4 = ras.arc[0].x;
1617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1618a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first, categorize the Bezier arc */
1619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1620a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y1 <= y4 )
1621a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1622a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y1;
1623a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y4;
1624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1625a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1627a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin1 = y4;
1628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax1 = y1;
1629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1631a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( y2 <= y3 )
1632a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1633a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y2;
1634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y3;
1635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1637a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1638a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymin2 = y3;
1639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ymax2 = y2;
1640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1641a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ymin2 < ymin1 || ymax2 > ymax1 )
1643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc has no given direction, split it! */
1645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Split_Cubic( ras.arc );
1646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc += 3;
1647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else if ( y1 == y4 )
1649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* this arc is flat, ignore it and pop it from the Bezier stack */
1651a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.arc -= 3;
1652a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
16559ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* detect a change of direction */
1658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.state != state_bez )
1659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
166037c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg          Bool  o = ( state_bez == Ascending_State )
166137c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg                      ? IS_BOTTOM_OVERSHOOT( y1 )
166237c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg                      : IS_TOP_OVERSHOOT( y1 );
166342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
166442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
166542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* finalize current profile if any */
1666cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg          if ( ras.state != Unknown_State &&
166742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               End_Profile( RAS_VARS o )  )
1668a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
167042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( New_Profile( RAS_VARS state_bez, o ) )
1671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* compute intersections */
16759ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg        if ( state_bez == Ascending_State )
1676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        else
1681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1684a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    } while ( ras.arc >= ras.arcs );
1686a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1687a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = x4;
1688a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = y4;
1689a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1692a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1697a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#undef  SWAP_
1698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#define SWAP_( x, y )  do                \
1699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       {                 \
1700a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         Long  swap = x; \
1701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                         \
1703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         x = y;          \
1704a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                         y = swap;       \
1705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                       } while ( 0 )
1706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1708a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1710a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Decompose_Curve                                                    */
1712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1714174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Scan the outline arrays in order to emit individual segments and   */
1715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
1716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    weird cases, like when the first point is off the curve, or when   */
1717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    there are simply no `on' points in the contour!                    */
1718a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    first   :: The index of the first point in the contour.            */
1721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    last    :: The index of the last point in the contour.             */
1723a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the curve.                */
1725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE on error.                              */
1728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
172952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
173052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Decompose_Curve( RAS_ARGS UShort  first,
173152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                            UShort  last,
1732a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg                            Int     flipped )
1733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_last;
1735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_control;
1736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector   v_start;
1737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  points;
1739a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  point;
1740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Vector*  limit;
1741a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    char*       tags;
1742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1743a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    UInt        tag;       /* current point's state           */
1744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    points = ras.outline.points;
1747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    limit  = points + last;
1748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.x = SCALED( points[first].x );
1750a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_start.y = SCALED( points[first].y );
1751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.x  = SCALED( points[last].x );
1752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_last.y  = SCALED( points[last].y );
1753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( flipped )
1755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1756a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_start.x, v_start.y );
1757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      SWAP_( v_last.x, v_last.y );
1758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1760a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    v_control = v_start;
1761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    point = points + first;
1763cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    tags  = ras.outline.tags + first;
176472271140434028186a49a5dc5925f0727559e46fWerner Lemberg
176572271140434028186a49a5dc5925f0727559e46fWerner Lemberg    /* set scan mode if necessary */
176672271140434028186a49a5dc5925f0727559e46fWerner Lemberg    if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE )
176772271140434028186a49a5dc5925f0727559e46fWerner Lemberg      ras.dropOutControl = (Byte)tags[0] >> 5;
176872271140434028186a49a5dc5925f0727559e46fWerner Lemberg
176972271140434028186a49a5dc5925f0727559e46fWerner Lemberg    tag = FT_CURVE_TAG( tags[0] );
1770a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* A contour cannot start with a cubic control point! */
1772b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CUBIC )
1773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Invalid_Outline;
1774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* check first point to determine origin */
1776b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( tag == FT_CURVE_TAG_CONIC )
1777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* first point is conic control.  Yes, this happens. */
1779b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1780a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at last point if it is on the curve */
1782a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start = v_last;
1783a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        limit--;
1784a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1785a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
1786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1787a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* if both first and last points are conic,         */
1788a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* start at their middle and record its position    */
1789a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* for closure                                      */
1790a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.x = ( v_start.x + v_last.x ) / 2;
1791a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_start.y = ( v_start.y + v_last.y ) / 2;
1792a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
17937be2a94a50109773459414687151d70a99a1b6bdSean McBride     /* v_last = v_start; */
1794a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1795a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point--;
1796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags--;
1797a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1798a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1799a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastX = v_start.x;
1800a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.lastY = v_start.y;
1801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( point < limit )
1803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      point++;
1805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tags++;
1806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      tag = FT_CURVE_TAG( tags[0] );
1808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      switch ( tag )
1810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
1811b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_ON:  /* emit a single line_to */
1812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x, y;
1814a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1815a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1816a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point->x );
1817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point->y );
1818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Line_To( RAS_VARS x, y ) )
1822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          continue;
1824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1826b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
1827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.x = SCALED( point[0].x );
1828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        v_control.y = SCALED( point[0].y );
1829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( flipped )
1831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          SWAP_( v_control.x, v_control.y );
1832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1833a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Do_Conic:
1834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( point < limit )
1835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          FT_Vector  v_middle;
1837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long       x, y;
1838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point++;
1841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags++;
1842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tag = FT_CURVE_TAG( tags[0] );
1843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x = SCALED( point[0].x );
1845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y = SCALED( point[0].y );
1846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x, y );
1849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1850b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag == FT_CURVE_TAG_ON )
1851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1854a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1857b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner          if ( tag != FT_CURVE_TAG_CONIC )
1858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.x = ( v_control.x + x ) / 2;
1861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_middle.y = ( v_control.y + y ) / 2;
1862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                  v_middle.x,  v_middle.y ) )
1865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.x = x;
1868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          v_control.y = y;
1869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Do_Conic;
1871a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                v_start.x,   v_start.y ) )
1875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Fail;
1876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        goto Close;
1878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1879b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner      default:  /* FT_CURVE_TAG_CUBIC */
1880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
1881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Long  x1, y1, x2, y2, x3, y3;
1882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point + 1 > limit                             ||
1885b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner               FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Invalid_Outline;
1887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          point += 2;
1889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          tags  += 2;
1890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = SCALED( point[-2].x );
1892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y1 = SCALED( point[-2].y );
1893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = SCALED( point[-1].x );
1894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          y2 = SCALED( point[-1].y );
1895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( flipped )
1897a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x1, y1 );
1899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            SWAP_( x2, y2 );
1900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( point <= limit )
1903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
1904c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy            x3 = SCALED( point[0].x );
1905c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy            y3 = SCALED( point[0].y );
1906c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy
1907c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy            if ( flipped )
1908c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy              SWAP_( x3, y3 );
1909c9de9cbd56caea5ceeab8d984e71441803c41aefYuriy Kaminskiy
1910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Fail;
1912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            continue;
1913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
1914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            goto Fail;
1917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Close;
1918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
1919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
1920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
1921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* close the contour with a line segment */
1923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      goto Fail;
1925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Close:
1927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
1928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Invalid_Outline:
1930059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg    ras.error = FT_THROW( Invalid );
1931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Fail:
1933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return FAILURE;
1934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
1935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1936a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
1938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
1940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Convert_Glyph                                                      */
1941a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
1943174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Convert a glyph into a series of segments and arcs and make a      */
1944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    profiles list with them.                                           */
1945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
1947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of curve.                    */
1948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
1949a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
1950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    SUCCESS on success, FAILURE if any error was encountered during    */
1951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    rendering.                                                         */
1952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
195352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
1954a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg  Convert_Glyph( RAS_ARGS Int  flipped )
1955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
1956a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    Int   i;
1957a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    UInt  start;
1958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fProfile = NULL;
1961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.joint    = FALSE;
1962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.fresh    = FALSE;
1963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
1965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.numTurns = 0;
1967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile         = (PProfile)ras.top;
1969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.cProfile->offset = ras.top;
1970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.num_Profs        = 0;
1971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1972a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    start = 0;
1973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    for ( i = 0; i < ras.outline.n_contours; i++ )
1975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
1976dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg      PProfile  lastProfile;
1977dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg      Bool      o;
197842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
197942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
19809ca7a157273201e4e40168e7b239e12bb813f9a7Werner Lemberg      ras.state    = Unknown_State;
1981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.gProfile = NULL;
1982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1983ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg      if ( Decompose_Curve( RAS_VARS (UShort)start,
1984ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg                                     (UShort)ras.outline.contours[i],
198542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                     flipped ) )
1986a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
1987a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1988ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg      start = (UShort)ras.outline.contours[i] + 1;
1989a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
1990cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg      /* we must now check whether the extreme arcs join or not */
1991a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( FRAC( ras.lastY ) == 0 &&
1992a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY >= ras.minY  &&
1993a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner           ras.lastY <= ras.maxY  )
199442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        if ( ras.gProfile                        &&
199542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg             ( ras.gProfile->flags & Flow_Up ) ==
199642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               ( ras.cProfile->flags & Flow_Up ) )
1997a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.top--;
1998a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* Note that ras.gProfile can be nil if the contour was too small */
1999a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* to be drawn.                                                   */
2000a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2001a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      lastProfile = ras.cProfile;
2002c242fe41ec634af32845cd17bcd1a0ee2653feb9Behdad Esfahbod      if ( ras.top != ras.cProfile->offset &&
2003c242fe41ec634af32845cd17bcd1a0ee2653feb9Behdad Esfahbod           ( ras.cProfile->flags & Flow_Up ) )
200442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        o = IS_TOP_OVERSHOOT( ras.lastY );
200542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      else
200642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
200742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg      if ( End_Profile( RAS_VARS o ) )
2008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return FAILURE;
2009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      /* close the `next profile in contour' linked list */
2011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.gProfile )
2012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        lastProfile->next = ras.gProfile;
2013a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2015a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( Finalize_Profile_Table( RAS_VAR ) )
2016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
2017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
20188edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
2019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2022a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2024a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
2025a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
2026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**                                                                     **/
2027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2033a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Init_Linked                                                          */
2034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Initializes an empty linked list.                                  */
2036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
203752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
203852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Init_Linked( TProfileList*  l )
2039a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *l = NULL;
2041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2043a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2044a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2046a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  InsNew                                                               */
2047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Inserts a new profile in a linked list.                            */
2049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
205052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
205152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  InsNew( PProfileList  list,
205252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
2053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2054a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
2055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long       x;
2056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2057a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2058a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2059a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    x       = profile->X;
2061a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2062a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
2063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( x < current->X )
2065a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        break;
2066a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
2067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
2068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    profile->link = current;
2071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *old          = profile;
2072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2073a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2074a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2077a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  DelOld                                                               */
2078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Removes an old profile from a linked list.                         */
2080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
208152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
208252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  DelOld( PProfileList  list,
208352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg          PProfile      profile )
2084a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2085a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current;
2086a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2088a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2089a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( current )
2092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2093a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current == profile )
2094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old = current->link;
2096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return;
2097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      old     = &current->link;
2100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      current = *old;
2101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* we should never get there, unless the profile was not part of */
2104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* the list.                                                     */
2105a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2106a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2109a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2110a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Sort                                                                 */
2111a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
2113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
2114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    and simple.                                                        */
2115a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
211652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
211752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Sort( PProfileList  list )
2118a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2119a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile  *old, current, next;
2120a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2121a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* First, set the new X coordinate of each profile */
2123ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    current = *list;
2124ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    while ( current )
2125ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    {
2126ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->X       = *current->offset;
212752aad9dfc6568b7eafefead5b49bad7e61f7938cWerner Lemberg      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
2128ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current->height--;
2129ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner      current = current->link;
2130ea5a981c7d000b11cf29dd7f1a9cf96defdff059David Turner    }
2131a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2132a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Then sort them */
2133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    old     = list;
2134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    current = *old;
2135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2136a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( !current )
2137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return;
2138a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    next = current->link;
2140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( next )
2142a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2143a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( current->X <= next->X )
2144a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = &current->link;
2146a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2147a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( !current )
2149a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return;
2150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2151a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2152a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2153a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *old          = next;
2154a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current->link = next->link;
2155a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        next->link    = current;
2156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2157a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        old     = list;
2158a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        current = *old;
2159a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      next = current->link;
2162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2164a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2165a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2167a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2168a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Vertical Sweep Procedure Set                                         */
2169a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the vertical black/white sweep   */
2171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  phase by the generic Draw_Sweep() function.                          */
2172a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2173a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
217552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
217652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Init( RAS_ARGS Short*  min,
217752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                Short*  max )
2178a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2179a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long  pitch = ras.target.pitch;
2180a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2181a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2182a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2183a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2184a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceIncr = (Short)-pitch;
2185a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs  = -*min * pitch;
2186a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( pitch > 0 )
2187ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg      ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
2188a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2189a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2190a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
219152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
219252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Span( RAS_ARGS Short       y,
219352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
219452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
219552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
219652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2197a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2198a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long   e1, e2;
2199a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte*  target;
2200a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2201f193637f63738eb451a6a23be70d763e78bc0c11Werner Lemberg    Int  dropOutControl = left->flags & 7;
2202f193637f63738eb451a6a23be70d763e78bc0c11Werner Lemberg
2203a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( y );
2204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2205a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2206a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2207a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2208d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    /* in high-precision mode, we need 12 digits after the comma to */
2209d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    /* represent multiples of 1/(1<<12) = 1/4096                    */
2210d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "  y=%d x=[%.12f;%.12f], drop-out=%d",
2211d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                y,
2212d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x1 / (double)ras.precision,
2213d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x2 / (double)ras.precision,
2214d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                dropOutControl ));
2215d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2216a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2217a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2218a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    e1 = TRUNC( CEILING( x1 ) );
2219a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2220426f0e0453f172dc411783356834fb6f01ef6cd7Werner Lemberg    if ( dropOutControl != 2                             &&
2221426f0e0453f172dc411783356834fb6f01ef6cd7Werner Lemberg         x2 - x1 - ras.precision <= ras.precision_jitter )
2222a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = e1;
2223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    else
2224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = TRUNC( FLOOR( x2 ) );
2225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2226a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e2 >= 0 && e1 < ras.bWidth )
2227a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2228a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg      Int   c1, c2;
2229dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg      Byte  f1, f2;
2230dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
2231dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
2232a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 < 0 )
2233a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = 0;
2234a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e2 >= ras.bWidth )
2235a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e2 = ras.bWidth - 1;
2236a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2237d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
2238d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2239a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2240a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 = (Short)( e2 >> 3 );
2241a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22428edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
22438edbcabce1b3756fb1921f85901dcce944bdf1e7David Turner      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2244a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2245a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      target = ras.bTarget + ras.traceOfs + c1;
2246a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c2 -= c1;
2247a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2248a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( c2 > 0 )
2249a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2250a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[0] |= f1;
2251a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
225294ffae5239631a18b8b5a39674c0afa8a992410eWerner Lemberg        /* memset() is slower than the following code on many platforms. */
2253a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* This is due to the fact that, in the vast majority of cases,  */
2254a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* the span length in bytes is relatively small.                 */
2255a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        c2--;
2256a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( c2 > 0 )
2257a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2258a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          *(++target) = 0xFF;
2259a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          c2--;
2260a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2261a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        target[1] |= f2;
2262a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2263a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2264a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        *target |= ( f1 & f2 );
2265a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2266d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2267d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "\n" ));
2268a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2269a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2270a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
227152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
227252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Drop( RAS_ARGS Short       y,
227352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x1,
227452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                FT_F26Dot6  x2,
227552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    left,
227652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                PProfile    right )
2277a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
22785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2279a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  c1, f1;
2280a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2281a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2282d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "  y=%d x=[%.12f;%.12f]",
2283d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                y,
2284d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x1 / (double)ras.precision,
2285d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x2 / (double)ras.precision ));
2286d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2287a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Drop-out control */
2288a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
22895df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   e2            x2                    x1           e1   */
22905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
22915df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 ^                     |                 */
22925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
22935df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*   +-------------+---------------------+------------+    */
22945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     |                 */
22955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                 |                     v                 */
22965df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*                                                         */
22975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* pixel         contour              contour       pixel  */
22985df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* center                                           center */
22995df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
23005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* drop-out mode    scan conversion rules (as defined in OpenType) */
23015df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* --------------------------------------------------------------- */
23025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  0                1, 2, 3                                       */
23035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  1                1, 2, 4                                       */
23045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  2                1, 2                                          */
23055df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  3                same as mode 2                                */
23065df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  4                1, 2, 5                                       */
23075df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  5                1, 2, 6                                       */
23085df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*  6, 7             same as mode 2                                */
23095df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
23105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
23115df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
23125df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2313a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2314a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2315a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
231672271140434028186a49a5dc5925f0727559e46fWerner Lemberg      Int  dropOutControl = left->flags & 7;
231772271140434028186a49a5dc5925f0727559e46fWerner Lemberg
231872271140434028186a49a5dc5925f0727559e46fWerner Lemberg
2319d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( ", drop-out=%d", dropOutControl ));
2320d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2321a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2322a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
232372271140434028186a49a5dc5925f0727559e46fWerner Lemberg        switch ( dropOutControl )
2324a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
23255df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
23265df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2327a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2328a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23295df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
23302f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg          pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2331a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2332a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23335df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
23345df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
2335a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23365df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* Drop-out Control Rules #4 and #6 */
23375df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
233842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* The specification neither provides an exact definition */
233942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* of a `stub' nor gives exact rules to exclude them.     */
2340a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
234142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* Here the constraints we use to recognize a stub.       */
2342a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2343a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  upper stub:                                           */
2344a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2345a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2346a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Right is the successor of P_Left in that contour */
2347a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the top of P_Left and P_Right                 */
2348a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2349a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*  lower stub:                                           */
2350a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
2351a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left and P_Right are in the same contour         */
2352a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - P_Left is the successor of P_Right in that contour */
2353a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*   - y is the bottom of P_Left                          */
2354a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /*                                                        */
235542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* We draw a stub if the following constraints are met.   */
235642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*                                                        */
235742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*   - for an upper or lower stub, there is top or bottom */
235842206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*     overshoot, respectively                            */
235942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*   - the covered interval is greater or equal to a half */
236042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /*     pixel                                              */
236142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg
236242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* upper stub test */
236342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( left->next == right                &&
236442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->height <= 0                  &&
236542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Top   &&
236642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half ) )
2367d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg            goto Exit;
2368a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
236942206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          /* lower stub test */
237042206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( right->next == left                 &&
237142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->start == y                    &&
237242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Bottom &&
237342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half  ) )
2374d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg            goto Exit;
2375a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
237672271140434028186a49a5dc5925f0727559e46fWerner Lemberg          if ( dropOutControl == 1 )
23775df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
23785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
23792f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg            pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
23805df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2381a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23825df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
2383d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          goto Exit;  /* no drop-out control */
23845df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2385a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
238629bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg        /* undocumented but confirmed: If the drop-out would result in a  */
23870039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        /* pixel outside of the bounding box, use the pixel inside of the */
23880039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        /* bounding box instead                                           */
238929bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg        if ( pxl < 0 )
239029bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg          pxl = e1;
23910039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        else if ( TRUNC( pxl ) >= ras.bWidth )
23920039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg          pxl = e2;
239329bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg
23945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
239537c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg        e1 = ( pxl == e1 ) ? e2 : e1;
2396a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2398a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
23995df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        c1 = (Short)( e1 >> 3 );
24005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1 = (Short)( e1 &  7 );
2401a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( e1 >= 0 && e1 < ras.bWidth                      &&
24035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg             ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
2404d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          goto Exit;
2405a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2406a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2407d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg        goto Exit;
2408a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2409a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
24105df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2411a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2412a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 >= 0 && e1 < ras.bWidth )
2413a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2414d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( " -> x=%d (drop-out)", e1 ));
2415d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2416a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      c1 = (Short)( e1 >> 3 );
2417914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      f1 = (Short)( e1 & 7 );
2418a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2419a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2420a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2421d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2422d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg  Exit:
2423d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "\n" ));
2424a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2425a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2426a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
242752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
242852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Vertical_Sweep_Step( RAS_ARG )
2429a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2430a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.traceOfs += ras.traceIncr;
2431a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2432a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2433a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2434a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2435a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2436a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Horizontal Sweep Procedure Set                                     */
2437a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2438a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  These four routines are used during the horizontal black/white     */
2439a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  sweep phase by the generic Draw_Sweep() function.                  */
2440a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                     */
2441a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /***********************************************************************/
2442a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
244352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
244452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
244552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  Short*  max )
2446a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2447a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing, really */
2448f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2449a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( min );
2450a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( max );
2451a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2452a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2453a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
245452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
245552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Span( RAS_ARGS Short       y,
245652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
245752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
245852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
245952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2460a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2461a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( left );
2462a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( right );
2463a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2464a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2465a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( x2 - x1 < ras.precision )
2466a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2467dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg      Long  e1, e2;
2468dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
2469dc624ca4dcac1cbfb6870414e6aaedba43aeb9eeWerner Lemberg
2470d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( "  x=%d y=[%.12f;%.12f]",
2471d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                  y,
2472d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                  x1 / (double)ras.precision,
2473d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                  x2 / (double)ras.precision ));
2474d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2475a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e1 = CEILING( x1 );
2476a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      e2 = FLOOR  ( x2 );
2477a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2478a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 )
2479a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2480a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        e1 = TRUNC( e1 );
2481a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2482b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg        if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
2483a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2484d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          Byte   f1;
2485d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          PByte  bits;
2486a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          PByte  p;
2487a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2488a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2489d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
2490d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2491d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          bits = ras.bTarget + ( y >> 3 );
2492d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          f1   = (Byte)( 0x80 >> ( y & 7 ) );
2493d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          p    = bits - e1 * ras.target.pitch;
2494d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2495a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( ras.target.pitch > 0 )
2496ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg            p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2497a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2498a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          p[0] |= f1;
2499a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2500a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2501d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2502d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( "\n" ));
2503a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2504a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2505a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2506a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
250752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
250852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
250952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x1,
251052005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  FT_F26Dot6  x2,
251152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    left,
251252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                                  PProfile    right )
2513a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
25145df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    Long   e1, e2, pxl;
2515a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PByte  bits;
2516a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Byte   f1;
2517a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2518a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2519d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "  x=%d y=[%.12f;%.12f]",
2520d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                y,
2521d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x1 / (double)ras.precision,
2522d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg                x2 / (double)ras.precision ));
2523d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2524a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* During the horizontal sweep, we only take care of drop-outs */
2525a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25265df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e1     +       <-- pixel center */
25275df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25285df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x1  ---+-->    <-- contour      */
25295df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25305df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25315df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* x2  <--+---    <-- contour      */
25325df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25335df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /*        |                        */
25345df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    /* e2     +       <-- pixel center */
25355df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
25365df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1  = CEILING( x1 );
25375df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e2  = FLOOR  ( x2 );
25385df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    pxl = e1;
2539a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2540a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( e1 > e2 )
2541a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
254272271140434028186a49a5dc5925f0727559e46fWerner Lemberg      Int  dropOutControl = left->flags & 7;
254372271140434028186a49a5dc5925f0727559e46fWerner Lemberg
254472271140434028186a49a5dc5925f0727559e46fWerner Lemberg
2545d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( ", dropout=%d", dropOutControl ));
2546d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2547a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( e1 == e2 + ras.precision )
2548a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
254972271140434028186a49a5dc5925f0727559e46fWerner Lemberg        switch ( dropOutControl )
2550a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
25515df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 0: /* simple drop-outs including stubs */
25525df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          pxl = e2;
2553a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2554a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25555df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 4: /* smart drop-outs including stubs */
25562f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg          pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2557a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          break;
2558a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25595df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 1: /* simple drop-outs excluding stubs */
25605df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        case 5: /* smart drop-outs excluding stubs  */
25615df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          /* see Vertical_Sweep_Drop for details */
2562a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2563a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* rightmost stub test */
256442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( left->next == right                &&
256542206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->height <= 0                  &&
256642206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Top   &&
256742206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half ) )
2568d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg            goto Exit;
2569a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2570a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          /* leftmost stub test */
257142206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg          if ( right->next == left                 &&
257242206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               left->start == y                    &&
257342206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg               !( left->flags & Overshoot_Bottom &&
257442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                  x2 - x1 >= ras.precision_half  ) )
2575d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg            goto Exit;
2576a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
257772271140434028186a49a5dc5925f0727559e46fWerner Lemberg          if ( dropOutControl == 1 )
25785df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg            pxl = e2;
25795df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          else
25802f2b780e00235356ffcf1e8f98e19f3bb1910ed2Werner Lemberg            pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
25815df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg          break;
2582a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25835df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        default: /* modes 2, 3, 6, 7 */
2584d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          goto Exit;  /* no drop-out control */
25855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        }
2586a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25870039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        /* undocumented but confirmed: If the drop-out would result in a  */
25880039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        /* pixel outside of the bounding box, use the pixel inside of the */
25890039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg        /* bounding box instead                                           */
259029bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg        if ( pxl < 0 )
259129bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg          pxl = e1;
2592b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
25930039d0120e08bdcbe88dac66f65003d3ed5251b4Werner Lemberg          pxl = e2;
259429bc310563d4c8c728adfa78e18af9e4d3c89116Werner Lemberg
25955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        /* check that the other pixel isn't set */
259637c72f66a56887ec25f4f541337b00e8ba69b9eeWerner Lemberg        e1 = ( pxl == e1 ) ? e2 : e1;
2597a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
25985df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        e1 = TRUNC( e1 );
2599a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26005df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits = ras.bTarget + ( y >> 3 );
26015df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        f1   = (Byte)( 0x80 >> ( y & 7 ) );
2602a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        bits -= e1 * ras.target.pitch;
26045df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        if ( ras.target.pitch > 0 )
2605ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg          bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2606a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2607b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg        if ( e1 >= 0                     &&
2608b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg             (ULong)e1 < ras.target.rows &&
2609b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg             *bits & f1                  )
2610d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg          goto Exit;
2611a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2612a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2613d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg        goto Exit;
2614a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2615a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26165df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    e1 = TRUNC( pxl );
2617a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2618b3500af717010137046ec4076d1e1c0641e33727Werner Lemberg    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
2619a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2620d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
2621d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2622d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      bits  = ras.bTarget + ( y >> 3 );
2623d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      f1    = (Byte)( 0x80 >> ( y & 7 ) );
2624a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits -= e1 * ras.target.pitch;
2625d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2626a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ras.target.pitch > 0 )
2627ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg        bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
2628a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2629a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bits[0] |= f1;
2630a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2631d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
2632d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg  Exit:
2633d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "\n" ));
2634a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2635a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2636a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
263752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
263852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Horizontal_Sweep_Step( RAS_ARG )
2639a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2640a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Nothing, really */
2641f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED_RASTER;
2642a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2643a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2644a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2645a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2646a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2647a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*  Generic Sweep Drawing routine                                        */
2648a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2649a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2650a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
265152005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static Bool
265252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Draw_Sweep( RAS_ARG )
2653a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2654a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         y, y_change, y_height;
2655a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2656a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    PProfile      P, Q, P_Left, P_Right;
2657a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2658a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short         min_Y, max_Y, top, bottom, dropouts;
2659a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2660a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Long          x1, x2, xs, e1, e2;
2661a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26623c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    TProfileList  waiting;
2663a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    TProfileList  draw_left, draw_right;
2664a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2665a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2666174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* initialize empty linked lists */
2667a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26683c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    Init_Linked( &waiting );
2669a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2670a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_left  );
2671a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Init_Linked( &draw_right );
2672a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2673a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* first, compute min and max Y */
2674a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2675a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P     = ras.fProfile;
2676a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    max_Y = (Short)TRUNC( ras.minY );
2677a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    min_Y = (Short)TRUNC( ras.maxY );
2678a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2679a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2680a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2681a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Q = P->link;
2682a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2683a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      bottom = (Short)P->start;
2684914b289f1623b1030b66537d3b3ce4b652e4606cWerner Lemberg      top    = (Short)( P->start + P->height - 1 );
2685a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
26865df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( min_Y > bottom )
26875df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        min_Y = bottom;
26885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( max_Y < top )
26895df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        max_Y = top;
2690a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2691a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P->X = 0;
26923c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      InsNew( &waiting, P );
2693a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2694a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = Q;
2695a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2696a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2697174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* check the Y-turns */
2698a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ras.numTurns == 0 )
2699a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2700059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      ras.error = FT_THROW( Invalid );
2701a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return FAILURE;
2702a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2703a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2704174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* now initialize the sweep */
2705a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2706a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2707a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2708174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* then compute the distance of each profile from min_Y */
2709a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27103c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg    P = waiting;
2711a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2712a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P )
2713a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2714ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg      P->countL = P->start - min_Y;
2715a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = P->link;
2716a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2717a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2718174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* let's go */
2719a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2720a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y        = min_Y;
2721a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    y_height = 0;
2722a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2723cbdba615115b0f07984130d9420ee7299ab0a3ccWerner Lemberg    if ( ras.numTurns > 0                     &&
2724a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner         ras.sizeBuff[-ras.numTurns] == min_Y )
2725a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.numTurns--;
2726a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2727a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.numTurns > 0 )
2728a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2729174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* check waiting list for new activations */
2730a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
27313c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg      P = waiting;
2732a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2733a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2734a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2735a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2736a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P->countL -= y_height;
2737a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->countL == 0 )
2738a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
27393c403e4c17fa68a8a7992fa347fda312e1bae2a0Werner Lemberg          DelOld( &waiting, P );
2740a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
274190c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          if ( P->flags & Flow_Up )
2742a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_left,  P );
274390c699af0cb6e40ba96f43e80433818c83d2560fWerner Lemberg          else
2744a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            InsNew( &draw_right, P );
2745a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2746a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2747a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2748a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2749a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2750174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* sort the drawing lists */
2751a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2752a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_left );
2753a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Sort( &draw_right );
2754a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2755a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
27568eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg      y_height = (Short)( y_change - y );
2757a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2758a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( y < y_change )
2759a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2760174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* let's trace */
2761a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2762a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts = 0;
2763a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2764a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left  = draw_left;
2765a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Right = draw_right;
2766a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2767a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        while ( P_Left )
2768a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2769a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x1 = P_Left ->X;
2770a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          x2 = P_Right->X;
2771a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2772a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( x1 > x2 )
2773a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          {
2774a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            xs = x1;
2775a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x1 = x2;
2776a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            x2 = xs;
2777a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2778a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
277971b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e1 = FLOOR( x1 );
278071b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          e2 = CEILING( x2 );
2781a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
278271b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          if ( x2 - x1 <= ras.precision &&
278371b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg               e1 != x1 && e2 != x2     )
278471b8f3f2ed06ce2a437b31e34c75e6aeab781640Werner Lemberg          {
2785ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg            if ( e1 > e2 || e2 == e1 + ras.precision )
2786a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            {
278772271140434028186a49a5dc5925f0727559e46fWerner Lemberg              Int  dropOutControl = P_Left->flags & 7;
278872271140434028186a49a5dc5925f0727559e46fWerner Lemberg
278972271140434028186a49a5dc5925f0727559e46fWerner Lemberg
279072271140434028186a49a5dc5925f0727559e46fWerner Lemberg              if ( dropOutControl != 2 )
2791ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              {
2792174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg                /* a drop-out was detected */
2793a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2794ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left ->X = x1;
2795ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Right->X = x2;
2796a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2797ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                /* mark profile for drop-out processing */
2798ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                P_Left->countL = 1;
2799ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg                dropouts++;
2800ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg              }
2801a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2802a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner              goto Skip_To_Next;
2803a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner            }
2804a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          }
2805a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2806a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
2807a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2808a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Skip_To_Next:
2809a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2810a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Left  = P_Left->link;
2811a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          P_Right = P_Right->link;
2812a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2813a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2814174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* handle drop-outs _after_ the span drawing --       */
2815174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* drop-out processing has been moved out of the loop */
2816174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg        /* for performance tuning                             */
2817a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( dropouts > 0 )
2818a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          goto Scan_DropOuts;
2819a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2820a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      Next_Line:
2821a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2822a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Step( RAS_VAR );
2823a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2824a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        y++;
2825a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2826a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( y < y_change )
2827a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2828a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_left  );
2829a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          Sort( &draw_right );
2830a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2831a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2832a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2833174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg      /* now finalize the profiles that need it */
2834a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2835a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_left;
2836a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2837a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2838a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2839a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
2840a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_left, P );
2841a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2842a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2843a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2844a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P = draw_right;
2845a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      while ( P )
2846a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2847a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        Q = P->link;
2848a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( P->height == 0 )
2849a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          DelOld( &draw_right, P );
2850a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P = Q;
2851a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2852a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2853a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2854174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg    /* for gray-scaling, flush the bitmap scanline cache */
2855a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( y <= max_Y )
2856a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2857a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step( RAS_VAR );
2858a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      y++;
2859a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2860a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2861a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
2862a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2863a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  Scan_DropOuts:
2864a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2865a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Left  = draw_left;
2866a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    P_Right = draw_right;
2867a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2868a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( P_Left )
2869a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2870a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( P_Left->countL )
2871a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2872a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        P_Left->countL = 0;
2873a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#if 0
2874a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        dropouts--;  /* -- this is useful when debugging only */
2875a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
2876a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.Proc_Sweep_Drop( RAS_VARS y,
2877a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left->X,
2878a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right->X,
2879a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Left,
2880a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner                                      P_Right );
2881a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2882a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2883a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Left  = P_Left->link;
2884a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      P_Right = P_Right->link;
2885a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2886a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2887a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    goto Next_Line;
2888a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2889a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2890a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2891a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2892a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2893a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
2894a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Single_Pass                                                 */
2895a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2896a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
2897174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Perform one sweep with sub-banding.                                */
2898a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2899a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Input>                                                               */
2900a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    flipped :: If set, flip the direction of the outline.              */
2901a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2902a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
2903a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Renderer error code.                                               */
2904a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
290552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
290652005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Single_Pass( RAS_ARGS Bool  flipped )
2907a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2908a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Short  i, j, k;
2909a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2910a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2911a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    while ( ras.band_top >= 0 )
2912a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
2913a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
2914a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
2915a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2916a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.top = ras.buff;
2917a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2918a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.error = Raster_Err_None;
2919a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2920a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( Convert_Glyph( RAS_VARS flipped ) )
2921a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2922a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.error != Raster_Err_Overflow )
2923a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return FAILURE;
2924a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2925a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.error = Raster_Err_None;
2926a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2927a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        /* sub-banding */
2928a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2929a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#ifdef DEBUG_RASTER
2930a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
2931a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner#endif
2932a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2933a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        i = ras.band_stack[ras.band_top].y_min;
2934a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        j = ras.band_stack[ras.band_top].y_max;
2935a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
29368eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        k = (Short)( ( i + j ) / 2 );
2937a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2938a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.band_top >= 7 || k < i )
2939a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        {
2940a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          ras.band_top = 0;
2941059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg          ras.error    = FT_THROW( Invalid );
2942a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2943a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          return ras.error;
2944a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        }
2945a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2946a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_min = k;
2947a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_stack[ras.band_top + 1].y_max = j;
2948a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
29498eb0353fec1494ab7d9fe9bb91a5954449ab30c1Werner Lemberg        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
2950a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2951a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top++;
2952a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2953a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      else
2954a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      {
2955a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        if ( ras.fProfile )
2956a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner          if ( Draw_Sweep( RAS_VAR ) )
2957a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner             return ras.error;
2958a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        ras.band_top--;
2959a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      }
2960a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
2961a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2962a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return SUCCESS;
2963a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
2964a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2965a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2966a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*************************************************************************/
2967a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2968a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Function>                                                            */
2969a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    Render_Glyph                                                       */
2970a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2971a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Description>                                                         */
2972174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  /*    Render a glyph in a bitmap.  Sub-banding if needed.                */
2973a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2974a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /* <Return>                                                              */
2975a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*    FreeType error code.  0 means success.                             */
2976a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /*                                                                       */
2977851e815127d47e85a575e1be7ff8cc265d5d7e79Werner Lemberg  static FT_Error
297852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  Render_Glyph( RAS_ARG )
2979a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
2980a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Error  error;
2981a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2982a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
2983a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    Set_High_Precision( RAS_VARS ras.outline.flags &
298442206ad86aac3c3c344fcd9730d80165514584c9Werner Lemberg                                 FT_OUTLINE_HIGH_PRECISION );
29855df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.scale_shift = ras.precision_shift;
29865df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
29875df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
29885df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      ras.dropOutControl = 2;
29895df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    else
29905df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    {
29915df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
29925df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 4;
29935df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      else
29945df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl = 0;
29955df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
29965df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
29975df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg        ras.dropOutControl += 1;
29985df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    }
29995df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg
3000ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg    ras.second_pass = (Bool)( !( ras.outline.flags      &
3001ca96fe01fa7687d43c062f5d48cf8fa919170be4Werner Lemberg                                 FT_OUTLINE_SINGLE_PASS ) );
3002a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3003a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Vertical Sweep */
3004d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
3005d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
3006a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
3007a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3008a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3009a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
3010a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3011a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_top            = 0;
3012a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.band_stack[0].y_min = 0;
3013a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
3014a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3015a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg    ras.bWidth  = (UShort)ras.target.width;
3016a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    ras.bTarget = (Byte*)ras.target.buffer;
3017a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3018a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
3019a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return error;
3020a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3021a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* Horizontal Sweep */
3022ce8853af8158368eae51b14c89dc3b79f48ce8ceWerner Lemberg    if ( ras.second_pass && ras.dropOutControl != 2 )
3023a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3024d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
3025d1ade6d11a1e31253180a19a2e0c6c1af0a8563fWerner Lemberg
3026a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3027a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3028a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3029a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3030a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3031a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_top            = 0;
3032a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ras.band_stack[0].y_min = 0;
3033a974e9acdf9c436a8520dd883179ae19d93a1c17Werner Lemberg      ras.band_stack[0].y_max = (Short)( ras.target.width - 1 );
3034a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3035a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3036a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner        return error;
3037a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3038a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3039f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    return Raster_Err_None;
3040a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3041a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3042a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
304352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
304495111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco  ft_black_init( black_PRaster  raster )
3045a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3046eca1f2790578ce8e9907ef3373ab69b7816b3093Werner Lemberg    FT_UNUSED( raster );
3047a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3048a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3049a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3050a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3051a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  /****                         a static object.                  *****/
3052a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3053a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
30549d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#ifdef STANDALONE_
3055a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3056a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
305752005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
3058174b8de3283c921d8bddf48325fe42ba7330a930Werner Lemberg  ft_black_new( void*       memory,
305952005c304229e2bfc54c0d406944d125d4849920Werner Lemberg                FT_Raster  *araster )
3060a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
306195111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco     static black_TRaster  the_raster;
306212cf031644ddd2531fa315e948aad24499adb251Werner Lemberg     FT_UNUSED( memory );
3063a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3064a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3065f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg     *araster = (FT_Raster)&the_raster;
306645cad2e5e15c08b682e87b5636cccfc941b3fe7dWerner Lemberg     FT_ZERO( &the_raster );
3067a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     ft_black_init( &the_raster );
3068a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3069a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner     return 0;
3070a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3071a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3072a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
307352005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
307452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  ft_black_done( FT_Raster  raster )
3075a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3076a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* nothing */
3077f9fccbee8b265a7576b358191e940299ebe60827Werner Lemberg    FT_UNUSED( raster );
3078a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3079a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3080a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
30819d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#else /* !STANDALONE_ */
3082a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3083a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
308452005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
308595111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco  ft_black_new( FT_Memory       memory,
308695111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco                black_PRaster  *araster )
3087a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
308895111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco    FT_Error       error;
308995111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco    black_PRaster  raster = NULL;
3090a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3091a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3092a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    *araster = 0;
3093e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    if ( !FT_NEW( raster ) )
3094a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    {
3095a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      raster->memory = memory;
3096a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      ft_black_init( raster );
3097a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3098a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      *araster = raster;
3099a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    }
3100a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3101a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    return error;
3102a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3103a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3104a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
310552005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
310695111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco  ft_black_done( black_PRaster  raster )
3107a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3108a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_Memory  memory = (FT_Memory)raster->memory;
310995111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco
311095111433853850345e4c3103b3bdf28a525ebb92Vinnie Falco
3111e459d742e6236df43f542b8c29dfdcf05d69716cDavid Turner    FT_FREE( raster );
3112a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3113a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3114a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31159d0b76d7f6e87b68ee739688be693f28094b23bfWerner Lemberg#endif /* !STANDALONE_ */
3116a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3117a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
311852005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static void
3119e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg  ft_black_reset( FT_Raster  raster,
3120e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg                  PByte      pool_base,
3121e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg                  ULong      pool_size )
3122a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3123a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    FT_UNUSED( raster );
3124a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    FT_UNUSED( pool_base );
3125a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    FT_UNUSED( pool_size );
3126a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3127a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3128a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31293e86711ebf6efdea405f8f35bc34baf737b744dfWerner Lemberg  static int
3130e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg  ft_black_set_mode( FT_Raster  raster,
3131e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg                     ULong      mode,
3132e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg                     void*      args )
3133a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
3134a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( raster );
3135a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    FT_UNUSED( mode );
3136e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg    FT_UNUSED( args );
3137a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31383e86711ebf6efdea405f8f35bc34baf737b744dfWerner Lemberg    return 0;
3139a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3140a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3141a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
314252005c304229e2bfc54c0d406944d125d4849920Werner Lemberg  static int
3143e9181aba2c5594f5fedba649170c6e8efbabdea2Werner Lemberg  ft_black_render( FT_Raster                raster,
3144fa420250c59414e432243feffb70be68654b8c27Werner Lemberg                   const FT_Raster_Params*  params )
3145a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  {
31468ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Outline*  outline    = (const FT_Outline*)params->source;
31478ae1dceb94effa59a307c0b778b37483f808f3d4Werner Lemberg    const FT_Bitmap*   target_map = params->target;
3148a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3149a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    black_TWorker  worker[1];
3150a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
315172a0653142420a060296ed261406ea61342fae8bAlexei Podtelezhnikov (Алексей Подтележников)    Long  buffer[FT_MAX_BLACK_POOL];
3152a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod
3153a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod
3154a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    if ( !raster )
3155059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Not_Ini );
3156a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31571ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline )
3158059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Invalid );
31591ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg
3160a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* return immediately if the outline is empty */
3161a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    if ( outline->n_points == 0 || outline->n_contours <= 0 )
3162a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner      return Raster_Err_None;
3163a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
31641ddd1b768dc3821e275e97c9391e54a14a8dc136Werner Lemberg    if ( !outline->contours || !outline->points )
3165059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Invalid );
3166a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3167c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( outline->n_points !=
3168c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg           outline->contours[outline->n_contours - 1] + 1 )
3169059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Invalid );
3170a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3171a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner    /* this version of the raster does not support direct rendering, sorry */
3172b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    if ( params->flags & FT_RASTER_FLAG_DIRECT )
3173059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Unsupported );
3174a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3175264b5e46c0d166c11360eb6c29edf2c178bb87c7Behdad Esfahbod    if ( params->flags & FT_RASTER_FLAG_AA )
3176264b5e46c0d166c11360eb6c29edf2c178bb87c7Behdad Esfahbod      return FT_THROW( Unsupported );
3177264b5e46c0d166c11360eb6c29edf2c178bb87c7Behdad Esfahbod
3178c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map )
3179059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Invalid );
3180c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3181c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    /* nothing to do */
3182c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->width || !target_map->rows )
3183c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg      return Raster_Err_None;
3184c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg
3185c938131856e288d7dd5d9e7c0437d0097b2ccc0cWerner Lemberg    if ( !target_map->buffer )
3186059bc335ce42220b222763379e89d0cbf2b949ebWerner Lemberg      return FT_THROW( Invalid );
31871eb9a43aa14e02b56d981bae334e6e24c63298f7David Turner
318831f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg    /* reject too large outline coordinates */
318931f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg    {
319031f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg      FT_Vector*  vec   = outline->points;
319131f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg      FT_Vector*  limit = vec + outline->n_points;
319231f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg
319331f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg
319431f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg      for ( ; vec < limit; vec++ )
319531f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg      {
319631f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg        if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
319731f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg             vec->y < -0x1000000L || vec->y > 0x1000000L )
319831f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg         return FT_THROW( Invalid );
319931f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg      }
320031f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg    }
320131f2dc19462774dd4e5b55f80cafcee07077e744Werner Lemberg
32025df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.outline = *outline;
32035df5dbb722cf008b3f617448d8d28fde4d725556Werner Lemberg    ras.target  = *target_map;
3204a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3205a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    worker->buff     = buffer;
3206a773c3041e024975241d110989f617f032c4b7e3Behdad Esfahbod    worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
32078a2c7f8fb804f3b74ea062f1c367b78d12c5b3f2David Turner
32088dc863587440d0a1d2eec2a7973a8eda99d2767dBehdad Esfahbod    return Render_Glyph( RAS_VAR );
3209a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner  }
3210a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3211a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
32124d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg  FT_DEFINE_RASTER_FUNCS(
32134d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg    ft_standard_raster,
32144d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg
3215b08fe2dc7af972a61f4e6bcadd7bb522861faec5David Turner    FT_GLYPH_FORMAT_OUTLINE,
32164d1f7af17b4b0966d5ed7fab215fc855fe459345Werner Lemberg
3217c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Raster_New_Func)     ft_black_new,       /* raster_new      */
3218c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Raster_Reset_Func)   ft_black_reset,     /* raster_reset    */
3219c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Raster_Set_Mode_Func)ft_black_set_mode,  /* raster_set_mode */
3220c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Raster_Render_Func)  ft_black_render,    /* raster_render   */
3221c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg    (FT_Raster_Done_Func)    ft_black_done       /* raster_done     */
3222c95b7652d8db19530c91e80d23c288bbf27f1b72Werner Lemberg  )
3223a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3224a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner
3225a4e2894e03de65c5e0cd14b11b6fa30b14ed6769David Turner/* END */
3226