1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  ftgrays.c                                                              */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    A new `perfect' anti-aliasing renderer (body).                       */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2000-2003, 2005-2013 by                                      */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This file can be compiled without the rest of the FreeType engine, by */
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* put the files `ftgrays.h' and `ftimage.h' into the current            */
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compilation directory.  Typically, you could do something like        */
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - copy `src/smooth/ftgrays.c' (this file) to your current directory   */
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   same directory                                                      */
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in        */
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*     cc -c -D_STANDALONE_ ftgrays.c                                    */
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The renderer can be initialized with a call to                        */
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated  */
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* with a call to `ft_gray_raster.raster_render'.                        */
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
38049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* See the comments and documentation in the file `ftimage.h' for more   */
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* details on how the raster works.                                      */
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This is a new anti-aliasing scan-converter for FreeType 2.  The       */
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* algorithm used here is _very_ different from the one in the standard  */
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `ftraster' module.  Actually, `ftgrays' computes the _exact_          */
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* coverage of the outline on each pixel cell.                           */
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* It is based on ideas that I initially found in Raph Levien's          */
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* excellent LibArt graphics library (see http://www.levien.com/libart   */
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* for more information, though the web pages do not tell anything       */
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* about the renderer; you'll have to dive into the source code to       */
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* understand how it works).                                             */
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Note, however, that this is a _very_ different implementation         */
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* compared to Raph's.  Coverage information is stored in a very         */
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* different way, and I don't use sorted vector paths.  Also, it doesn't */
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* use floating point values.                                            */
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This renderer has the following advantages:                           */
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - It doesn't need an intermediate bitmap.  Instead, one can supply a  */
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   callback function that will be called by the renderer to draw gray  */
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   spans on any target surface.  You can thus do direct composition on */
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   any kind of bitmap, provided that you give the renderer the right   */
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   callback.                                                           */
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on   */
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   each pixel cell.                                                    */
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - It performs a single pass on the outline (the `standard' FT2        */
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   renderer makes two passes).                                         */
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - It can easily be modified to render to _any_ number of gray levels  */
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   cheaply.                                                            */
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* - For small (< 20) pixel sizes, it is faster than the standard        */
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   renderer.                                                           */
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* messages during execution.                                            */
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef  FT_COMPONENT
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_COMPONENT  trace_smooth
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
940a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef _STANDALONE_
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
97a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* Auxiliary macros for token concatenation. */
98a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_ERR_XCAT( x, y )  x ## y
99a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1020a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* define this to dump debugging information */
1030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* #define FT_DEBUG_LEVEL_TRACE */
1040a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1050a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <stdio.h>
1080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <stdarg.h>
1090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
111aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#include <stddef.h>
1120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <string.h>
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <setjmp.h>
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <limits.h>
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_UINT_MAX  UINT_MAX
116aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#define FT_INT_MAX   INT_MAX
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_memset   memset
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_setjmp   setjmp
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_longjmp  longjmp
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_jmp_buf  jmp_buf
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
124aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevichtypedef ptrdiff_t  FT_PtrDist;
125aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Mode      -2
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Outline   -1
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Argument  -3
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Memory_Overflow   -4
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_BEGIN_HEADER
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_END_HEADER
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftimage.h"
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftgrays.h"
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This macro is used to indicate that a function parameter is unused. */
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ANSI compilers (e.g. LCC).                                          */
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_UNUSED( x )  (x) = (x)
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1450a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1460a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
1470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  void
1510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_Message( const char*  fmt,
1520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              ... )
1530a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  {
1540a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_list  ap;
1550a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1560a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1570a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_start( ap, fmt );
1580a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    vfprintf( stderr, fmt, ap );
1590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_end( ap );
1600a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  }
1610a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* empty function useful for setting a breakpoint to catch errors */
164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  int
165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_Throw( int          error,
166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            int          line,
167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            const char*  file )
168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UNUSED( error );
170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UNUSED( line );
171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UNUSED( file );
172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return 0;
174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* we don't handle tracing levels in stand-alone mode; */
1780a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifndef FT_TRACE5
1790a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE5( varformat )  FT_Message varformat
1800a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
1810a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifndef FT_TRACE7
1820a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE7( varformat )  FT_Message varformat
1830a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_ERROR
1850a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_ERROR( varformat )   FT_Message varformat
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_THROW( e )                               \
189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          ( FT_Throw( FT_ERR_CAT( ErrRaster, e ),   \
190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      __LINE__,                     \
191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      __FILE__ )                  | \
192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_ERR_CAT( ErrRaster, e )            )
193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1940a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#else /* !FT_DEBUG_LEVEL_TRACE */
1950a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
1970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
1980a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_THROW( e )   FT_ERR_CAT( ErrRaster_, e )
200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
2010a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
2020a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* !FT_DEBUG_LEVEL_TRACE */
2030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
205295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define FT_DEFINE_OUTLINE_FUNCS( class_,               \
206295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 move_to_, line_to_,   \
207295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 conic_to_, cubic_to_, \
208295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 shift_, delta_ )      \
209295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          static const FT_Outline_Funcs class_ =       \
210295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          {                                            \
211295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            move_to_,                                  \
212295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            line_to_,                                  \
213295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            conic_to_,                                 \
214295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            cubic_to_,                                 \
215295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            shift_,                                    \
216295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            delta_                                     \
217295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         };
2188583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
219295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_,            \
220295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_new_, raster_reset_,       \
221295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_set_mode_, raster_render_, \
222295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_done_ )                    \
223295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          const FT_Raster_Funcs class_ =                          \
224295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          {                                                       \
225295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            glyph_format_,                                        \
226295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_new_,                                          \
227295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_reset_,                                        \
228295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_set_mode_,                                     \
229295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_render_,                                       \
230295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_done_                                          \
231295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         };
232295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !_STANDALONE_ */
235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftgrays.h"
239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_OUTLINE_H
242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftsmerrs.h"
244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
245295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ftspic.h"
246295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define Smooth_Err_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define Smooth_Err_Memory_Overflow  Smooth_Err_Out_Of_Memory
249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !_STANDALONE_ */
253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_MEM_SET
256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_MEM_ZERO
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* as usual, for the speed hungry :-) */
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
265e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef RAS_ARG
266e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef RAS_ARG_
267e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef RAS_VAR
268e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef RAS_VAR_
269e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_STATIC_RASTER
271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
272e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#define RAS_ARG   gray_PWorker  worker
273e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#define RAS_ARG_  gray_PWorker  worker,
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR   worker
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR_  worker,
277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* FT_STATIC_RASTER */
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_ARG   /* empty */
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_ARG_  /* empty */
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR   /* empty */
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR_  /* empty */
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* FT_STATIC_RASTER */
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* must be at least 6 bits! */
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PIXEL_BITS  8
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
291e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef FLOOR
292e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef CEILING
293e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef TRUNC
294e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang#undef SCALED
295e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ONE_PIXEL       ( 1L << PIXEL_BITS )
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PIXEL_MASK      ( -1L << PIXEL_BITS )
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TRUNC( x )      ( (TCoord)( (x) >> PIXEL_BITS ) )
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define SUBPIXELS( x )  ( (TPos)(x) << PIXEL_BITS )
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FLOOR( x )      ( (x) & -ONE_PIXEL )
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if PIXEL_BITS >= 6
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   TYPE DEFINITIONS                                                    */
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* don't change the following types to FT_Int or FT_Pos, since we might */
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* need to define them to "float" or "double" when experimenting with   */
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* new algorithms                                                       */
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
322295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  typedef long  TCoord;   /* integer scanline/pixel coordinate */
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef long  TPos;     /* sub-pixel coordinate              */
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* determine the type used to store cell areas.  This normally takes at */
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* least PIXEL_BITS*2 + 1 bits.  On 16-bit systems, we need to use      */
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `long' instead of `int', otherwise bad things happen                 */
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if PIXEL_BITS <= 7
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef int  TArea;
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* PIXEL_BITS >= 8 */
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* approximately determine the size of integers using an ANSI-C header */
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if FT_UINT_MAX == 0xFFFFU
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef long  TArea;
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef int   TArea;
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* PIXEL_BITS >= 8 */
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* maximum number of gray spans in a call to the span callback */
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MAX_GRAY_SPANS  32
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct TCell_*  PCell;
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TCell_
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
353e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TPos    x;     /* same with gray_TWorker.ex    */
354e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TCoord  cover; /* same with gray_TWorker.cover */
355e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TArea   area;
356e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    PCell   next;
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TCell;
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
361e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  typedef struct  gray_TWorker_
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TCoord  ex, ey;
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    min_ex, max_ex;
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    min_ey, max_ey;
366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    count_ex, count_ey;
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TArea   area;
369295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TCoord  cover;
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     invalid;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    PCell       cells;
373295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_PtrDist  max_cells;
374295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_PtrDist  num_cells;
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TCoord  cx, cy;
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    x,  y;
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    last_ey;
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   bez_stack[32 * 3 + 1];
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         lev_stack[32];
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Outline  outline;
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap   target;
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_BBox     clip_box;
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         num_gray_spans;
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Raster_Span_Func  render_span;
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    void*                render_span_data;
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int                  span_y;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  band_size;
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  band_shoot;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_jmp_buf  jump_buffer;
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    void*       buffer;
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long        buffer_size;
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PCell*     ycells;
404295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TPos       ycount;
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  } gray_TWorker, *gray_PWorker;
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
409295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_STATIC_RASTER
410295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define ras  (*worker)
411295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#else
412e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  static gray_TWorker  ras;
413295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif
414295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
415295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
416e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  typedef struct gray_TRaster_
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
418e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    void*         buffer;
419e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    long          buffer_size;
420e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    int           band_size;
421e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    void*         memory;
422e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_PWorker  worker;
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
424e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  } gray_TRaster, *gray_PRaster;
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Initialize the cells table.                                           */
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_init_cells( RAS_ARG_ void*  buffer,
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   long            byte_size )
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.buffer      = buffer;
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.buffer_size = byte_size;
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ycells      = (PCell*) buffer;
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cells       = NULL;
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_cells   = 0;
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_cells   = 0;
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.area        = 0;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover       = 0;
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid     = 1;
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Compute the outline bounding box.                                     */
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_compute_cbox( RAS_ARG )
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Outline*  outline = &ras.outline;
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*   vec     = outline->points;
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*   limit   = vec + outline->n_points;
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points <= 0 )
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.min_ex = ras.max_ex = 0;
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.min_ey = ras.max_ey = 0;
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ex = ras.max_ex = vec->x;
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ey = ras.max_ey = vec->y;
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec++;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; vec < limit; vec++ )
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TPos  x = vec->x;
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TPos  y = vec->y;
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x < ras.min_ex ) ras.min_ex = x;
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x > ras.max_ex ) ras.max_ex = x;
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( y < ras.min_ey ) ras.min_ey = y;
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( y > ras.max_ey ) ras.max_ey = y;
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* truncate the bounding box to integer pixels */
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ex = ras.min_ex >> 6;
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ey = ras.min_ey >> 6;
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Record the current cell in the table.                                 */
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static PCell
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_find_cell( RAS_ARG )
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PCell  *pcell, cell;
501295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TPos    x = ras.ex;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
5040a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( x > ras.count_ex )
5050a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      x = ras.count_ex;
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    pcell = &ras.ycells[ras.ey];
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for (;;)
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell = *pcell;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cell == NULL || cell->x > x )
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cell->x == x )
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pcell = &cell->next;
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.num_cells >= ras.max_cells )
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_longjmp( ras.jump_buffer, 1 );
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell        = ras.cells + ras.num_cells++;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->x     = x;
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->area  = 0;
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->cover = 0;
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->next  = *pcell;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pcell      = cell;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cell;
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_record_cell( RAS_ARG )
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !ras.invalid && ( ras.area | ras.cover ) )
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell  cell = gray_find_cell( RAS_VAR );
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell->area  += ras.area;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell->cover += ras.cover;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Set the current cell to a new position.                               */
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_set_cell( RAS_ARG_ TCoord  ex,
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          TCoord  ey )
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Move the cell pointer to a new position.  We set the `invalid'      */
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* flag to indicate that the cell isn't part of those we're interested */
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* in during the render phase.  This means that:                       */
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* . the new vertical position must be within min_ey..max_ey-1.        */
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* . the new horizontal position must be strictly less than max_ex     */
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Note that if a cell is to the left of the clipping region, it is    */
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* actually set to the (min_ex-1) horizontal position.                 */
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* All cells that are on the left of the clipping region go to the */
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* min_ex - 1 horizontal position.                                 */
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey -= ras.min_ey;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex > ras.max_ex )
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = ras.max_ex;
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex -= ras.min_ex;
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex < 0 )
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = -1;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* are we moving to a different cell ? */
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex != ras.ex || ey != ras.ey )
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* record the current one if it is valid */
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !ras.invalid )
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_record_cell( RAS_VAR );
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  = 0;
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover = 0;
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ex      = ex;
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ey      = ey;
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              ex >= ras.count_ex           );
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Start a new contour at a given cell.                                  */
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_start_cell( RAS_ARG_ TCoord  ex,
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            TCoord  ey )
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex > ras.max_ex )
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = (TCoord)( ras.max_ex );
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex < ras.min_ex )
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = (TCoord)( ras.min_ex - 1 );
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.area    = 0;
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover   = 0;
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ex      = ex - ras.min_ex;
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ey      = ey - ras.min_ey;
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.last_ey = SUBPIXELS( ey );
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid = 0;
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ ex, ey );
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Render a scanline as one or more cells.                               */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_scanline( RAS_ARG_ TCoord  ey,
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TPos    x1,
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TCoord  y1,
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TPos    x2,
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TCoord  y2 )
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
633a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    TCoord  ex1, ex2, fx1, fx2, delta, mod;
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long    p, first, dx;
635295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    int     incr;
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dx = x2 - x1;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex1 = TRUNC( x1 );
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex2 = TRUNC( x2 );
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* trivial case.  Happens often */
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( y1 == y2 )
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gray_set_cell( RAS_VAR_ ex2, ey );
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* everything is located in a single cell.  That is easy! */
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                        */
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex1 == ex2 )
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = y2 - y1;
657295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      ras.area  += (TArea)(( fx1 + fx2 ) * delta);
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* ok, we'll have to render a run of adjacent cells on the same */
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scanline...                                                  */
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                              */
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = ONE_PIXEL;
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr  = 1;
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx < 0 )
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = fx1 * ( y2 - y1 );
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = 0;
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      incr  = -1;
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dx    = -dx;
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta = (TCoord)( p / dx );
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mod   = (TCoord)( p % dx );
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mod < 0 )
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta--;
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod += (TCoord)dx;
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
685295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    ras.area  += (TArea)(( fx1 + first ) * delta);
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover += delta;
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex1 += incr;
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ ex1, ey );
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y1  += delta;
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex1 != ex2 )
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
694a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      TCoord  lift, rem;
695a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
696a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p    = ONE_PIXEL * ( y2 - y1 + delta );
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      lift = (TCoord)( p / dx );
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      rem  = (TCoord)( p % dx );
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( rem < 0 )
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        lift--;
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rem += (TCoord)dx;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod -= (int)dx;
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ex1 != ex2 )
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = lift;
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mod  += rem;
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mod >= 0 )
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          mod -= (TCoord)dx;
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta++;
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
718295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        ras.area  += (TArea)(ONE_PIXEL * delta);
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.cover += delta;
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        y1        += delta;
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ex1       += incr;
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_set_cell( RAS_VAR_ ex1, ey );
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta      = y2 - y1;
727295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    ras.area  += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover += delta;
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Render a given line as a series of scanlines.                         */
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_line( RAS_ARG_ TPos  to_x,
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             TPos  to_y )
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
740295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TCoord  ey1, ey2, fy1, fy2, mod;
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    dx, dy, x, x2;
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long    p, first;
743295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    int     delta, rem, lift, incr;
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey1 = TRUNC( ras.last_ey );
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fy1 = (TCoord)( ras.y - ras.last_ey );
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dx = to_x - ras.x;
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dy = to_y - ras.y;
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* XXX: we should do something about the trivial case where dx == 0, */
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*      as it happens very often!                                    */
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* perform vertical clipping */
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  min, max;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      min = ey1;
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      max = ey2;
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ey1 > ey2 )
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = ey2;
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = ey1;
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( min >= ras.max_ey || max < ras.min_ey )
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto End;
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* everything is on a single scanline */
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ey1 == ey2 )
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto End;
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* vertical line - avoid calling gray_render_scanline */
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr = 1;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx == 0 )
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  ex     = TRUNC( ras.x );
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
787295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      TArea   area;
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = ONE_PIXEL;
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy < 0 )
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = 0;
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        incr  = -1;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = (int)( first - fy1 );
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  += (TArea)two_fx * delta;
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ey1       += incr;
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
802295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      gray_set_cell( RAS_VAR_ ex, ey1 );
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = (int)( first + first - ONE_PIXEL );
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      area  = (TArea)two_fx * delta;
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ey1 != ey2 )
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.area  += area;
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.cover += delta;
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ey1       += incr;
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gray_set_cell( RAS_VAR_ ex, ey1 );
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = (int)( fy2 - ONE_PIXEL + first );
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  += (TArea)two_fx * delta;
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto End;
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* ok, we have to render several scanlines */
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p     = ( ONE_PIXEL - fy1 ) * dx;
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = ONE_PIXEL;
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr  = 1;
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dy < 0 )
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = fy1 * dx;
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = 0;
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      incr  = -1;
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dy    = -dy;
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta = (int)( p / dy );
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    mod   = (int)( p % dy );
837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( mod < 0 )
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta--;
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod += (TCoord)dy;
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = ras.x + delta;
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey1 += incr;
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ey1 != ey2 )
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = ONE_PIXEL * dx;
852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      lift  = (int)( p / dy );
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      rem   = (int)( p % dy );
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( rem < 0 )
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        lift--;
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rem += (int)dy;
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod -= (int)dy;
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ey1 != ey2 )
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = lift;
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mod  += rem;
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mod >= 0 )
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          mod -= (int)dy;
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta++;
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x2 = x + delta;
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_render_scanline( RAS_VAR_ ey1, x,
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       (TCoord)( ONE_PIXEL - first ), x2,
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       (TCoord)first );
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x = x2;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ey1 += incr;
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_render_scanline( RAS_VAR_ ey1, x,
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   (TCoord)( ONE_PIXEL - first ), to_x,
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   fy2 );
885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  End:
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.x       = to_x;
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.y       = to_y;
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.last_ey = SUBPIXELS( ey2 );
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_split_conic( FT_Vector*  base )
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  a, b;
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = base[2].x;
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x;
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].x = ( base[2].x + b ) / 2;
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x = ( base[0].x + b ) / 2;
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = ( a + b ) / 2;
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = base[2].y;
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y;
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].y = ( base[2].y + b ) / 2;
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y = ( base[0].y + b ) / 2;
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = ( a + b ) / 2;
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_conic( RAS_ARG_ const FT_Vector*  control,
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  to )
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos        dx, dy;
918e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TPos        min, max, y;
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         top, level;
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int*        levels;
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
924e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    levels = ras.lev_stack;
925e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
9268583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc      = ras.bez_stack;
9278583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[0].x = UPSCALE( to->x );
9288583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[0].y = UPSCALE( to->y );
9298583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[1].x = UPSCALE( control->x );
9308583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[1].y = UPSCALE( control->y );
9318583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[2].x = ras.x;
9328583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    arc[2].y = ras.y;
933e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    top      = 0;
9348583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
9358583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
9368583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx < dy )
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dx = dy;
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
940e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( dx < ONE_PIXEL / 4 )
941e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      goto Draw;
942e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
943e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    /* short-cut the arc that crosses the current band */
944e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    min = max = arc[0].y;
945e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
946e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    y = arc[1].y;
947e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y < min ) min = y;
948e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y > max ) max = y;
949e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
950e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    y = arc[2].y;
951e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y < min ) min = y;
952e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y > max ) max = y;
953e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
954e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
955e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      goto Draw;
956e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
9578583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    level = 0;
958e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    do
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
9608583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      dx >>= 2;
9618583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      level++;
962e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    } while ( dx > ONE_PIXEL / 4 );
963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    levels[0] = level;
965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
966c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    do
967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      level = levels[top];
969e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      if ( level > 0 )
970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_split_conic( arc );
972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        arc += 2;
973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        top++;
974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        levels[top] = levels[top - 1] = level - 1;
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Draw:
9798583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
9808583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      top--;
9818583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      arc -= 2;
982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
983c3ee10bfa1f76a18500b487de9c85757375b48f3David 'Digit' Turner    } while ( top >= 0 );
984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_split_cubic( FT_Vector*  base )
989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  a, b, c, d;
991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].x = base[3].x;
994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].x;
995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].x;
996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].x = a = ( base[0].x + c ) / 2;
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].x = b = ( base[3].x + d ) / 2;
998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = a = ( a + c ) / 2;
1000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = b = ( b + c ) / 2;
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].x = ( a + b ) / 2;
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].y = base[3].y;
1004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].y;
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].y;
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].y = a = ( base[0].y + c ) / 2;
1007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].y = b = ( base[3].y + d ) / 2;
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = a = ( a + c ) / 2;
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = b = ( b + c ) / 2;
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].y = ( a + b ) / 2;
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_cubic( RAS_ARG_ const FT_Vector*  control1,
1017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  control2,
1018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  to )
1019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
1021e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TPos        min, max, y;
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc      = ras.bez_stack;
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0].x = UPSCALE( to->x );
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0].y = UPSCALE( to->y );
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1].x = UPSCALE( control2->x );
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1].y = UPSCALE( control2->y );
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2].x = UPSCALE( control1->x );
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2].y = UPSCALE( control1->y );
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[3].x = ras.x;
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[3].y = ras.y;
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1034e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    /* Short-cut the arc that crosses the current band. */
1035e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    min = max = arc[0].y;
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1037e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    y = arc[1].y;
1038e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y < min )
1039e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      min = y;
1040e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y > max )
1041e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      max = y;
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1043e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    y = arc[2].y;
1044e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y < min )
1045e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      min = y;
1046e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y > max )
1047e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      max = y;
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1049e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    y = arc[3].y;
1050e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y < min )
1051e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      min = y;
1052e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( y > max )
1053e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      max = y;
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1055e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
1056e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      goto Draw;
10578583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
1058e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    for (;;)
1059e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    {
10608583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      /* Decide whether to split or draw. See `Rapid Termination          */
10618583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
10628583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      /* F. Hain, at                                                      */
10638583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
10648583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10658583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      {
10668583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        TPos  dx, dy, dx_, dy_;
10678583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        TPos  dx1, dy1, dx2, dy2;
10688583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        TPos  L, s, s_limit;
10698583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10708583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10718583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* dx and dy are x and y components of the P0-P3 chord vector. */
10728583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dx = arc[3].x - arc[0].x;
10738583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dy = arc[3].y - arc[0].y;
10748583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10758583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* L is an (under)estimate of the Euclidean distance P0-P3.       */
10768583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10778583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated   */
10788583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* with least maximum error by                                    */
10798583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10808583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*   r_upperbound = dx + (sqrt(2) - 1) * dy  ,                    */
10818583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10828583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
10838583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* error of no more than 8.4%.                                    */
10848583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10858583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* Similarly, some elementary calculus shows that r can be        */
10868583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* underestimated with least maximum error by                     */
10878583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10888583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*   r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx                    */
10898583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                  + sqrt(2 - sqrt(2)) / 2 * dy  .               */
10908583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                                                */
10918583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* 236/256 and 97/256 are (under)estimates of the two algebraic   */
10928583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* numbers, giving an error of no more than 8.1%.                 */
10938583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10948583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dx_ = FT_ABS( dx );
10958583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dy_ = FT_ABS( dy );
10968583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
10978583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* This is the same as                     */
10988583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*                                         */
10998583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*   L = ( 236 * FT_MAX( dx_, dy_ )        */
11008583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /*       + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
11018583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        L = ( dx_ > dy_ ? 236 * dx_ +  97 * dy_
11028583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner                        :  97 * dx_ + 236 * dy_ ) >> 8;
11038583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11048583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* Avoid possible arithmetic overflow below by splitting. */
11058583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( L > 32767 )
11068583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          goto Split;
11078583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11088583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
11098583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        s_limit = L * (TPos)( ONE_PIXEL / 6 );
11108583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11118583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
11128583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dx1 = arc[1].x - arc[0].x;
11138583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dy1 = arc[1].y - arc[0].y;
11148583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        s = FT_ABS( dy * dx1 - dx * dy1 );
11158583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11168583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( s > s_limit )
11178583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          goto Split;
11188583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11198583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
11208583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dx2 = arc[2].x - arc[0].x;
11218583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        dy2 = arc[2].y - arc[0].y;
11228583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        s = FT_ABS( dy * dx2 - dx * dy2 );
11238583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11248583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        if ( s > s_limit )
11258583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          goto Split;
11268583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
1127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* Split super curvy segments where the off points are so far
1128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           from the chord that the angles P0-P1-P3 or P0-P2-P3 become
1129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           acute as detected by appropriate dot products. */
1130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
1131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
11328583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner          goto Split;
11338583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11348583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        /* No reason to split. */
11358583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        goto Draw;
1136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
11388583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    Split:
11398583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      gray_split_cubic( arc );
11408583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      arc += 3;
11418583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      continue;
1142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
11438583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    Draw:
11448583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
11458583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11468583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      if ( arc == ras.bez_stack )
11478583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner        return;
11488583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner
11498583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner      arc -= 3;
11508583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner    }
11518583905b8952672a083f21fd8945f329b98aa35bDavid 'Digit' Turner  }
1152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_move_to( const FT_Vector*  to,
1156e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                gray_PWorker      worker )
1157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  x, y;
1159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* record current cell, if any */
1162295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_record_cell( RAS_VAR );
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* start to a new position */
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = UPSCALE( to->x );
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y = UPSCALE( to->y );
1167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1168295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    worker->x = x;
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    worker->y = y;
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_line_to( const FT_Vector*  to,
1178e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                gray_PWorker      worker )
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1180295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_conic_to( const FT_Vector*  control,
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  to,
1188e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                 gray_PWorker      worker )
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1190295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_conic( RAS_VAR_ control, to );
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_cubic_to( const FT_Vector*  control1,
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  control2,
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  to,
1199e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                 gray_PWorker      worker )
1200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1201295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_cubic( RAS_VAR_ control1, control2, to );
1202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_span( int             y,
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    int             count,
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    const FT_Span*  spans,
1210e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                    gray_PWorker    worker )
1211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    unsigned char*  p;
1213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*      map = &worker->target;
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, compute the scanline offset */
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = (unsigned char*)map->buffer - y * map->pitch;
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( map->pitch >= 0 )
1219aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich      p += (unsigned)( ( map->rows - 1 ) * map->pitch );
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, spans++ )
1222049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      unsigned char  coverage = spans->coverage;
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage )
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* For small-spans it is faster to do it by ourselves than
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         * calling `memset'.  This is mainly due to the cost of the
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         * function call.
1231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( spans->len >= 8 )
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          unsigned char*  q = p + spans->x;
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          switch ( spans->len )
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 7: *q++ = (unsigned char)coverage;
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 6: *q++ = (unsigned char)coverage;
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 5: *q++ = (unsigned char)coverage;
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 4: *q++ = (unsigned char)coverage;
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 3: *q++ = (unsigned char)coverage;
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 2: *q++ = (unsigned char)coverage;
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 1: *q   = (unsigned char)coverage;
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ;
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_hline( RAS_ARG_ TCoord  x,
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       TCoord  y,
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       TPos    area,
1261295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                       TCoord  acount )
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    int  coverage;
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute the coverage line's coverage, depending on the    */
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* outline fill rule                                         */
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                           */
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                           */
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                    /* use range 0..256 */
1273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( coverage < 0 )
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      coverage = -coverage;
1275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      coverage &= 511;
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage > 256 )
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 512 - coverage;
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( coverage == 256 )
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 255;
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* normal non-zero winding rule */
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage >= 256 )
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 255;
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y += (TCoord)ras.min_ey;
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x += (TCoord)ras.min_ex;
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
12960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( x >= 32767 )
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      x = 32767;
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1299295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* FT_Span.y is an integer, so limit our coordinates appropriately */
1300295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( y >= FT_INT_MAX )
1301295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      y = FT_INT_MAX;
1302295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( coverage )
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Span*  span;
1306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      int       count;
1307a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* see whether we can add this span to the current list */
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count = ras.num_gray_spans;
1311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span  = ras.gray_spans + count - 1;
1312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( count > 0                          &&
1313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ras.span_y == y                    &&
1314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           (int)span->x + span->len == (int)x &&
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           span->coverage == coverage         )
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span->len = (unsigned short)( span->len + acount );
1318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return;
1319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ras.render_span && count > 0 )
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.render_span( ras.span_y, count, ras.gray_spans,
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           ras.render_span_data );
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13270a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        if ( count > 0 )
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          int  n;
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE7(( "y = %3d ", ras.span_y ));
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          span = ras.gray_spans;
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( n = 0; n < count; n++, span++ )
13370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE7(( "[%d..%d]:%02x ",
13380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        span->x, span->x + span->len - 1, span->coverage ));
13390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE7(( "\n" ));
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13420a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* FT_DEBUG_LEVEL_TRACE */
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.num_gray_spans = 0;
1345295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        ras.span_y         = (int)y;
1346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        count = 0;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span  = ras.gray_spans;
1349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span++;
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add a gray span to the current list */
1354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->x        = (short)x;
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->len      = (unsigned short)acount;
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->coverage = (unsigned char)coverage;
1357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.num_gray_spans++;
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13630a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* to be called while in the debugger --                                */
13660a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* this function causes a compiler warning since it is unused otherwise */
13670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  static void
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_dump_cells( RAS_ARG )
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  yindex;
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( yindex = 0; yindex < ras.ycount; yindex++ )
1374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell  cell;
1376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      printf( "%3d:", yindex );
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
1381295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      printf( "\n" );
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13860a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* FT_DEBUG_LEVEL_TRACE */
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  yindex;
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( target );
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.num_cells == 0 )
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_gray_spans = 0;
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
14020a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE7(( "gray_sweep: start\n" ));
14030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( yindex = 0; yindex < ras.ycount; yindex++ )
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell   cell  = ras.ycells[yindex];
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  cover = 0;
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  x     = 0;
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; cell != NULL; cell = cell->next )
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1413295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        TPos  area;
1414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cell->x > x && cover != 0 )
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      cell->x - x );
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cover += cell->cover;
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        area   = cover * ( ONE_PIXEL * 2 ) - cell->area;
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( area != 0 && cell->x >= 0 )
1424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x = cell->x + 1;
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cover != 0 )
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    ras.count_ex - x );
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.render_span && ras.num_gray_spans > 0 )
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span( ras.span_y, ras.num_gray_spans,
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       ras.gray_spans, ras.render_span_data );
14370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1438a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifdef FT_DEBUG_LEVEL_TRACE
1439a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1440a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( ras.num_gray_spans > 0 )
1441a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
1442a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Span*  span;
1443a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      int       n;
1444a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1445a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1446a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_TRACE7(( "y = %3d ", ras.span_y ));
1447a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      span = ras.gray_spans;
1448a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
1449a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE7(( "[%d..%d]:%02x ",
1450a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                    span->x, span->x + span->len - 1, span->coverage ));
1451a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_TRACE7(( "\n" ));
1452a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
1453a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
14540a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE7(( "gray_sweep: end\n" ));
1455a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1456a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif /* FT_DEBUG_LEVEL_TRACE */
1457a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef _STANDALONE_
1462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*  The following function should only compile in stand-alone mode,      */
1466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*  i.e., when building this component without the rest of FreeType.     */
1467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FT_Outline_Decompose                                               */
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
14760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    Walk over an outline's structure to decompose it into individual   */
14770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    segments and Bézier arcs.  This function is also able to emit      */
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    `move to' and `close to' operations to indicate the start and end  */
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    of new contours in the outline.                                    */
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    outline        :: A pointer to the source target.                  */
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14840a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    func_interface :: A table of `emitters', i.e., function pointers   */
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      called during decomposition to indicate path     */
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      operations.                                      */
1487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* <InOut>                                                               */
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    user           :: A typeless pointer which is passed to each       */
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      emitter during the decomposition.  It can be     */
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      used to store the state during the               */
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      decomposition.                                   */
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Error code.  0 means success.                                      */
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  static int
14980a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_Outline_Decompose( const FT_Outline*        outline,
14990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        const FT_Outline_Funcs*  func_interface,
15000a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        void*                    user )
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef SCALED
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define SCALED( x )  ( ( (x) << shift ) - delta )
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_last;
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_control;
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_start;
1508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  point;
1510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit;
1511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tags;
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15130a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    int         error;
15140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int   n;         /* index of contour in outline     */
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int   first;     /* index of first point in contour */
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char  tag;       /* current point's state           */
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    int   shift;
15200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    TPos  delta;
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15230a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( !outline || !func_interface )
1524a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
15250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
15260a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    shift = func_interface->shift;
15270a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    delta = func_interface->delta;
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_contours; n++ )
1531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int  last;  /* index of last point in contour */
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
15360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last  = outline->contours[n];
15380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      if ( last < 0 )
15390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        goto Invalid_Outline;
1540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      limit = outline->points + last;
1541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15420a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_start   = outline->points[first];
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_start.x = SCALED( v_start.x );
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_start.y = SCALED( v_start.y );
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15460a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last   = outline->points[last];
15470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.x = SCALED( v_last.x );
15480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.y = SCALED( v_last.y );
1549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_control = v_start;
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point = outline->points + first;
15530a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      tags  = outline->tags   + first;
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag   = FT_CURVE_TAG( tags[0] );
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A contour cannot start with a cubic control point! */
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CUBIC )
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Invalid_Outline;
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check first point to determine origin */
1561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CONIC )
1562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* first point is conic control.  Yes, this happens. */
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at last point if it is on the curve */
1567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start = v_last;
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          limit--;
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if both first and last points are conic,         */
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at their middle and record its position    */
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for closure                                      */
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.x = ( v_start.x + v_last.x ) / 2;
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.y = ( v_start.y + v_last.y ) / 2;
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_last = v_start;
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point--;
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags--;
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15840a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  move to (%.2f, %.2f)\n",
15850a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->move_to( &v_start, user );
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( point < limit )
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags++;
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag = FT_CURVE_TAG( tags[0] );
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        switch ( tag )
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_ON:  /* emit a single line_to */
1599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.x = SCALED( point->x );
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.y = SCALED( point->y );
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  line to (%.2f, %.2f)\n",
16070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec.x / 64.0, vec.y / 64.0 ));
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->line_to( &vec, user );
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
16150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          v_control.x = SCALED( point->x );
16160a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          v_control.y = SCALED( point->y );
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        Do_Conic:
16190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          if ( point < limit )
16200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          {
16210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_Vector  vec;
16220a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_Vector  v_middle;
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            point++;
16260a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            tags++;
16270a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            tag = FT_CURVE_TAG( tags[0] );
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec.x = SCALED( point->x );
16300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec.y = SCALED( point->y );
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( tag == FT_CURVE_TAG_ON )
16330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            {
16340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  conic to (%.2f, %.2f)"
16350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with control (%.2f, %.2f)\n",
16360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
16370a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          v_control.x / 64.0, v_control.y / 64.0 ));
16380a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              error = func_interface->conic_to( &v_control, &vec, user );
1639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
1640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
16410a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              continue;
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16440a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( tag != FT_CURVE_TAG_CONIC )
16450a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              goto Invalid_Outline;
16460a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_middle.x = ( v_control.x + vec.x ) / 2;
16480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_middle.y = ( v_control.y + vec.y ) / 2;
16490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  conic to (%.2f, %.2f)"
16510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with control (%.2f, %.2f)\n",
16520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_middle.x / 64.0, v_middle.y / 64.0,
16530a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_control.x / 64.0, v_control.y / 64.0 ));
16540a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            error = func_interface->conic_to( &v_control, &v_middle, user );
16550a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( error )
16560a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              goto Exit;
16570a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16580a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_control = vec;
16590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            goto Do_Conic;
1660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16620a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE5(( "  conic to (%.2f, %.2f)"
16630a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      " with control (%.2f, %.2f)\n",
16640a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_start.x / 64.0, v_start.y / 64.0,
16650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_control.x / 64.0, v_control.y / 64.0 ));
16660a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          error = func_interface->conic_to( &v_control, &v_start, user );
16670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          goto Close;
16680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        default:  /* FT_CURVE_TAG_CUBIC */
1670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec1, vec2;
1672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point + 1 > limit                             ||
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
1677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point += 2;
1679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags  += 2;
1680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec1.x = SCALED( point[-2].x );
1682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec1.y = SCALED( point[-2].y );
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec2.x = SCALED( point[-1].x );
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec2.y = SCALED( point[-1].y );
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point <= limit )
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Vector  vec;
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.x = SCALED( point->x );
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.y = SCALED( point->y );
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16950a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  cubic to (%.2f, %.2f)"
16960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
16970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
16980a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec1.x / 64.0, vec1.y / 64.0,
16990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec2.x / 64.0, vec2.y / 64.0 ));
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
17060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  cubic to (%.2f, %.2f)"
17070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
17080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_start.x / 64.0, v_start.y / 64.0,
17090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec1.x / 64.0, vec1.y / 64.0,
17100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec2.x / 64.0, vec2.y / 64.0 ));
1711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
1712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Close;
1713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* close the contour with a line segment */
17180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  line to (%.2f, %.2f)\n",
17190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
1720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->line_to( &v_start, user );
1721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   Close:
1723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
17290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
17330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Invalid_Outline:
1737a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return FT_THROW( Invalid_Outline );
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* _STANDALONE_ */
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1743e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  typedef struct  gray_TBand_
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  min, max;
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1747e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  } gray_TBand;
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1749295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_DEFINE_OUTLINE_FUNCS(func_interface,
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Outline_MoveTo_Func) gray_move_to,
1751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Outline_LineTo_Func) gray_line_to,
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Outline_ConicTo_Func)gray_conic_to,
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      (FT_Outline_CubicTo_Func)gray_cubic_to,
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      0,
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      0
1756295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    )
1757295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
1758295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static int
1759295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  gray_convert_glyph_inner( RAS_ARG )
1760295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
1761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    volatile int  error = 0;
1763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1764295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifdef FT_CONFIG_OPTION_PIC
1765295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Outline_Funcs func_interface;
1766295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      Init_Class_func_interface(&func_interface);
1767295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif
17680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ft_setjmp( ras.jump_buffer ) == 0 )
1770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
1772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gray_record_cell( RAS_VAR );
1773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1775a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      error = FT_THROW( Memory_Overflow );
1776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_convert_glyph( RAS_ARG )
1783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1784e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_TBand            bands[40];
1785e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_TBand* volatile  band;
1786e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    int volatile          n, num_bands;
1787e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    TPos volatile         min, max, max_y;
1788e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    FT_BBox*              clip;
1789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Set up state in the raster object */
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_compute_cbox( RAS_VAR );
1793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* clip to target bitmap, exit if nothing to do */
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    clip = &ras.clip_box;
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
1802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
1803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
1805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
1806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.count_ex = ras.max_ex - ras.min_ex;
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.count_ey = ras.max_ey - ras.min_ey;
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* set up vertical bands */
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
18120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( num_bands == 0 )
18130a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      num_bands = 1;
18140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( num_bands >= 39 )
18150a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      num_bands = 39;
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.band_shoot = 0;
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min   = ras.min_ey;
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max_y = ras.max_ey;
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < num_bands; n++, min = max )
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      max = min + ras.band_size;
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( n == num_bands - 1 || max > max_y )
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = max_y;
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      bands[0].min = min;
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      bands[0].max = max;
1830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      band         = bands;
1831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( band >= bands )
1833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        TPos  bottom, top, middle;
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        int   error;
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PCell  cells_max;
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          int    yindex;
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          long   cell_start, cell_end, cell_mod;
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.ycells = (PCell*)ras.buffer;
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.ycount = band->max - band->min;
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cell_start = sizeof ( PCell ) * ras.ycount;
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cell_mod   = cell_start % sizeof ( TCell );
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( cell_mod > 0 )
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            cell_start += sizeof ( TCell ) - cell_mod;
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cell_end  = ras.buffer_size;
1852e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang          cell_end -= cell_end % sizeof ( TCell );
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cells_max = (PCell)( (char*)ras.buffer + cell_end );
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.cells = (PCell)( (char*)ras.buffer + cell_start );
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ras.cells >= cells_max )
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto ReduceBands;
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.max_cells = cells_max - ras.cells;
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ras.max_cells < 2 )
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto ReduceBands;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( yindex = 0; yindex < ras.ycount; yindex++ )
1864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ras.ycells[yindex] = NULL;
1865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.num_cells = 0;
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.invalid   = 1;
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.min_ey    = band->min;
1870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.max_ey    = band->max;
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.count_ey  = band->max - band->min;
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = gray_convert_glyph_inner( RAS_VAR );
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !error )
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_sweep( RAS_VAR_ &ras.target );
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          band--;
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( error != ErrRaster_Memory_Overflow )
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 1;
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ReduceBands:
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* render pool overflow; we will reduce the render band by half */
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        bottom = band->min;
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        top    = band->max;
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        middle = bottom + ( ( top - bottom ) >> 1 );
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* This is too complex for a single scanline; there must */
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* be some problems.                                     */
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( middle == bottom )
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
18940a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1895295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 1;
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( bottom-top >= ras.band_size )
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.band_shoot++;
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[1].min = bottom;
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[1].max = middle;
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[0].min = middle;
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[0].max = top;
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band++;
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.band_shoot > 8 && ras.band_size > 16 )
1912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.band_size = ras.band_size / 2;
1913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1919e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang  gray_raster_render( gray_PRaster             raster,
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      const FT_Raster_Params*  params )
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const FT_Outline*  outline    = (const FT_Outline*)params->source;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    const FT_Bitmap*   target_map = params->target;
1924e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_PWorker       worker;
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !raster || !raster->buffer || !raster->buffer_size )
1928a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Argument );
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline )
1931a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Outline );
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* return immediately if the outline is empty */
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points == 0 || outline->n_contours <= 0 )
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline->contours || !outline->points )
1938a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Outline );
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points !=
1941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           outline->contours[outline->n_contours - 1] + 1 )
1942a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Outline );
1943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    worker = raster->worker;
1945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if direct mode is not set, we must have a target bitmap */
19470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
1948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map )
1950a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        return FT_THROW( Invalid_Argument );
1951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* nothing to do */
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map->width || !target_map->rows )
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
1955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map->buffer )
1957a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        return FT_THROW( Invalid_Argument );
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* this version does not support monochrome rendering */
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_AA ) )
1962a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return FT_THROW( Invalid_Mode );
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute clipping box */
19650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
1966049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute clip box from target pixmap */
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMin = 0;
1969049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMin = 0;
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMax = target_map->width;
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMax = target_map->rows;
1972049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( params->flags & FT_RASTER_FLAG_CLIP )
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box = params->clip_box;
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMin = -32768L;
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMin = -32768L;
1979049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMax =  32767L;
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMax =  32767L;
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1983295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
1984049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.outline        = *outline;
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_cells      = 0;
1987049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid        = 1;
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.band_size      = raster->band_size;
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_gray_spans = 0;
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( params->flags & FT_RASTER_FLAG_DIRECT )
1992049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1993049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span_data = params->user;
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
19960a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    else
19970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    {
19980a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.target           = *target_map;
19990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
20000a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.render_span_data = &ras;
20010a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2003295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gray_convert_glyph( RAS_VAR );
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
20070a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
20080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /****                         a static object.                   *****/
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef _STANDALONE_
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_new( void*       memory,
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Raster*  araster )
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2016e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    static gray_TRaster  the_raster;
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( memory );
2019049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2021049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *araster = (FT_Raster)&the_raster;
2022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
2023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_done( FT_Raster  raster )
2030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* nothing */
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( raster );
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2035aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#else /* !_STANDALONE_ */
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_new( FT_Memory   memory,
2039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Raster*  araster )
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2041e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    FT_Error      error;
2042e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_PRaster  raster = NULL;
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *araster = 0;
2046e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      raster->memory = memory;
2049e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      *araster       = (FT_Raster)raster;
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_done( FT_Raster  raster )
2058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2059e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    FT_Memory  memory = (FT_Memory)((gray_PRaster)raster)->memory;
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( raster );
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2065aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#endif /* !_STANDALONE_ */
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_reset( FT_Raster  raster,
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     char*      pool_base,
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     long       pool_size )
2072049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2073e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    gray_PRaster  rast = (gray_PRaster)raster;
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( raster )
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2078e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang      if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2080e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang        gray_PWorker  worker = (gray_PWorker)pool_base;
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2082049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->worker      = worker;
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->buffer      = pool_base +
2085e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                              ( ( sizeof ( gray_TWorker ) +
2086e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang                                  sizeof ( TCell ) - 1 )  &
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                ~( sizeof ( TCell ) - 1 ) );
2088049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->buffer_size = (long)( ( pool_base + pool_size ) -
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                    (char*)rast->buffer ) &
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                      ~( sizeof ( TCell ) - 1 );
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->band_size   = (int)( rast->buffer_size /
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                     ( sizeof ( TCell ) * 8 ) );
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
2096049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->buffer      = NULL;
2097049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->buffer_size = 0;
2098049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rast->worker      = NULL;
2099049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2104295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
2105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GLYPH_FORMAT_OUTLINE,
2106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_New_Func)     gray_raster_new,
2108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Reset_Func)   gray_raster_reset,
2109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Set_Mode_Func)0,
2110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Render_Func)  gray_raster_render,
2111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Done_Func)    gray_raster_done
2112295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  )
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
21160a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
21170a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
21180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* Local Variables: */
21190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* coding: utf-8    */
21200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* End:             */
2121