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/*                                                                         */
7fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki/*  Copyright 2000-2015 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  /*                                                                       */
27ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* - copy `include/ftimage.h' and `src/smooth/ftgrays.h' to the same     */
28ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /*   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
97fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* The size in bytes of the render pool used by the scan-line converter  */
98fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /* to do all of its work.                                                */
99fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_RENDER_POOL_SIZE  16384L
100fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
101fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
102727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* Auxiliary macros for token concatenation. */
103727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_ERR_XCAT( x, y )  x ## y
104727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
105727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1069c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define FT_BEGIN_STMNT  do {
1079c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod#define FT_END_STMNT    } while ( 0 )
1089c745321260bb728ab1cd1c8fd5f075854b2ad49Behdad Esfahbod
109fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_MAX( a, b )  ( (a) > (b) ? (a) : (b) )
110fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_ABS( a )     ( (a) < 0 ? -(a) : (a) )
111fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
112fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
113fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  /*
114fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki   *  Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
115fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki   *  algorithm.  We use alpha = 1, beta = 3/8, giving us results with a
116fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki   *  largest error less than 7% compared to the exact value.
117fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki   */
118fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki#define FT_HYPOT( x, y )                 \
119fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          ( x = FT_ABS( x ),             \
120fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            y = FT_ABS( y ),             \
121fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            x > y ? x + ( 3 * y >> 3 )   \
122fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                  : y + ( 3 * x >> 3 ) )
123fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
124727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* define this to dump debugging information */
1260a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* #define FT_DEBUG_LEVEL_TRACE */
1270a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1280a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <stdio.h>
1310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <stdarg.h>
1320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
134aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#include <stddef.h>
1350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#include <string.h>
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <setjmp.h>
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <limits.h>
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_UINT_MAX  UINT_MAX
139aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#define FT_INT_MAX   INT_MAX
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_memset   memset
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_setjmp   setjmp
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_longjmp  longjmp
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ft_jmp_buf  jmp_buf
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
147aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevichtypedef ptrdiff_t  FT_PtrDist;
148aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Mode      -2
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Outline   -1
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Invalid_Argument  -3
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Memory_Overflow   -4
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_BEGIN_HEADER
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_END_HEADER
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftimage.h"
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftgrays.h"
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1610a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* This macro is used to indicate that a function parameter is unused. */
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* ANSI compilers (e.g. LCC).                                          */
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_UNUSED( x )  (x) = (x)
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
1700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1710a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1720a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1730a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  void
1740a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_Message( const char*  fmt,
1750a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              ... )
1760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  {
1770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_list  ap;
1780a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1790a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1800a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_start( ap, fmt );
1810a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    vfprintf( stderr, fmt, ap );
1820a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    va_end( ap );
1830a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  }
1840a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
185727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
186727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* empty function useful for setting a breakpoint to catch errors */
187727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  int
188727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  FT_Throw( int          error,
189727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            int          line,
190727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            const char*  file )
191727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  {
192727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( error );
193727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( line );
194727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_UNUSED( file );
195727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
196727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return 0;
197727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  }
198727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
199727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2000a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* we don't handle tracing levels in stand-alone mode; */
2010a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifndef FT_TRACE5
2020a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE5( varformat )  FT_Message varformat
2030a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
2040a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifndef FT_TRACE7
2050a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE7( varformat )  FT_Message varformat
2060a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_ERROR
2080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_ERROR( varformat )   FT_Message varformat
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
211727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_THROW( e )                               \
212727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease          ( FT_Throw( FT_ERR_CAT( ErrRaster, e ),   \
213727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                      __LINE__,                     \
214727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                      __FILE__ )                  | \
215727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease            FT_ERR_CAT( ErrRaster, e )            )
216727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2170a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#else /* !FT_DEBUG_LEVEL_TRACE */
2180a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
2190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
2200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
2210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
222727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_THROW( e )   FT_ERR_CAT( ErrRaster_, e )
223727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
2240a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
2250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* !FT_DEBUG_LEVEL_TRACE */
2260a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
228295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define FT_DEFINE_OUTLINE_FUNCS( class_,               \
229295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 move_to_, line_to_,   \
230295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 conic_to_, cubic_to_, \
231295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                 shift_, delta_ )      \
232295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          static const FT_Outline_Funcs class_ =       \
233295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          {                                            \
234295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            move_to_,                                  \
235295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            line_to_,                                  \
236295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            conic_to_,                                 \
237295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            cubic_to_,                                 \
238295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            shift_,                                    \
239295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            delta_                                     \
240295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         };
2417f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
242295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_,            \
243295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_new_, raster_reset_,       \
244295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_set_mode_, raster_render_, \
245295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                                raster_done_ )                    \
246295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          const FT_Raster_Funcs class_ =                          \
247295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          {                                                       \
248295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            glyph_format_,                                        \
249295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_new_,                                          \
250295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_reset_,                                        \
251295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_set_mode_,                                     \
252295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_render_,                                       \
253295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner            raster_done_                                          \
254295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner         };
255295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
256727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* !_STANDALONE_ */
258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftgrays.h"
262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_DEBUG_H
264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_OUTLINE_H
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include "ftsmerrs.h"
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
268295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#include "ftspic.h"
269295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
270727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define Smooth_Err_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
271727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define Smooth_Err_Memory_Overflow  Smooth_Err_Out_Of_Memory
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
273727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
275049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* !_STANDALONE_ */
276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
277727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_MEM_SET
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_MEM_ZERO
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* as usual, for the speed hungry :-) */
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
28841371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef RAS_ARG
28941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef RAS_ARG_
29041371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef RAS_VAR
29141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef RAS_VAR_
29241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifndef FT_STATIC_RASTER
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
29541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#define RAS_ARG   gray_PWorker  worker
29641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#define RAS_ARG_  gray_PWorker  worker,
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR   worker
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR_  worker,
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* FT_STATIC_RASTER */
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_ARG   /* empty */
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_ARG_  /* empty */
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR   /* empty */
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define RAS_VAR_  /* empty */
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* FT_STATIC_RASTER */
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* must be at least 6 bits! */
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PIXEL_BITS  8
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
31441371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef FLOOR
31541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef CEILING
31641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef TRUNC
31741371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier#undef SCALED
31841371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ONE_PIXEL       ( 1L << PIXEL_BITS )
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define PIXEL_MASK      ( -1L << PIXEL_BITS )
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define TRUNC( x )      ( (TCoord)( (x) >> PIXEL_BITS ) )
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define SUBPIXELS( x )  ( (TPos)(x) << PIXEL_BITS )
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FLOOR( x )      ( (x) & -ONE_PIXEL )
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if PIXEL_BITS >= 6
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* Compute `dividend / divisor' and return both its quotient and     */
337ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* remainder, cast to a specific type.  This macro also ensures that */
338ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* the remainder is always positive.                                 */
339ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
340ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  FT_BEGIN_STMNT                                                   \
341ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    (quotient)  = (type)( (dividend) / (divisor) );                \
342ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    (remainder) = (type)( (dividend) % (divisor) );                \
343ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( (remainder) < 0 )                                         \
344ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    {                                                              \
345ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      (quotient)--;                                                \
346ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      (remainder) += (type)(divisor);                              \
347ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    }                                                              \
348ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  FT_END_STMNT
349ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
350ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#ifdef  __arm__
351ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* Work around a bug specific to GCC which make the compiler fail to */
352ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* optimize a division and modulo operation on the same parameters   */
353ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* into a single call to `__aeabi_idivmod'.  See                     */
354ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /*                                                                   */
355ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /*  http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721                */
356ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#undef FT_DIV_MOD
357ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#define FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
358ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  FT_BEGIN_STMNT                                                   \
359ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    (quotient)  = (type)( (dividend) / (divisor) );                \
360ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    (remainder) = (type)( (dividend) - (quotient) * (divisor) );   \
361ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( (remainder) < 0 )                                         \
362ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    {                                                              \
363ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      (quotient)--;                                                \
364ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      (remainder) += (type)(divisor);                              \
365ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    }                                                              \
366ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  FT_END_STMNT
367ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif /* __arm__ */
368ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
369ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*   TYPE DEFINITIONS                                                    */
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* don't change the following types to FT_Int or FT_Pos, since we might */
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* need to define them to "float" or "double" when experimenting with   */
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* new algorithms                                                       */
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
379295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  typedef long  TCoord;   /* integer scanline/pixel coordinate */
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef long  TPos;     /* sub-pixel coordinate              */
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* determine the type used to store cell areas.  This normally takes at */
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* least PIXEL_BITS*2 + 1 bits.  On 16-bit systems, we need to use      */
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* `long' instead of `int', otherwise bad things happen                 */
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if PIXEL_BITS <= 7
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef int  TArea;
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else /* PIXEL_BITS >= 8 */
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* approximately determine the size of integers using an ANSI-C header */
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#if FT_UINT_MAX == 0xFFFFU
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef long  TArea;
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#else
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef int   TArea;
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* PIXEL_BITS >= 8 */
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
402727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* maximum number of gray spans in a call to the span callback */
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_MAX_GRAY_SPANS  32
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct TCell_*  PCell;
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  typedef struct  TCell_
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
41041371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    TPos    x;     /* same with gray_TWorker.ex    */
41141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    TCoord  cover; /* same with gray_TWorker.cover */
41241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    TArea   area;
41341371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    PCell   next;
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  } TCell;
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
418ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
419ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* We disable the warning `structure was padded due to   */
420ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* __declspec(align())' in order to compile cleanly with */
421ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease  /* the maximum level of warnings.                        */
422ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#pragma warning( push )
423ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#pragma warning( disable : 4324 )
424ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif /* _MSC_VER */
425ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
42641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  typedef struct  gray_TWorker_
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
428fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    ft_jmp_buf  jump_buffer;
429fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TCoord  ex, ey;
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    min_ex, max_ex;
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    min_ey, max_ey;
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    count_ex, count_ey;
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TArea   area;
436295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TCoord  cover;
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int     invalid;
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
43941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    PCell       cells;
440295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_PtrDist  max_cells;
441295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    FT_PtrDist  num_cells;
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TCoord  cx, cy;
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    x,  y;
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    last_ey;
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   bez_stack[32 * 3 + 1];
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         lev_stack[32];
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Outline  outline;
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap   target;
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_BBox     clip_box;
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         num_gray_spans;
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Raster_Span_Func  render_span;
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    void*                render_span_data;
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int                  span_y;
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  band_size;
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  band_shoot;
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    void*       buffer;
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long        buffer_size;
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PCell*     ycells;
469295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TPos       ycount;
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
47141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  } gray_TWorker, *gray_PWorker;
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
473ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#if defined( _MSC_VER )
474ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#pragma warning( pop )
475ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease#endif
476ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifndef FT_STATIC_RASTER
479295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#define ras  (*worker)
480295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#else
48141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  static gray_TWorker  ras;
482295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif
483295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
484295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
48541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  typedef struct gray_TRaster_
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
48741371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    void*         memory;
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
48941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  } gray_TRaster, *gray_PRaster;
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  /* Initialize the cells table.                                           */
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_init_cells( RAS_ARG_ void*  buffer,
499fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                            long   byte_size )
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.buffer      = buffer;
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.buffer_size = byte_size;
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ycells      = (PCell*) buffer;
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cells       = NULL;
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_cells   = 0;
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_cells   = 0;
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.area        = 0;
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover       = 0;
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid     = 1;
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Compute the outline bounding box.                                     */
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_compute_cbox( RAS_ARG )
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Outline*  outline = &ras.outline;
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*   vec     = outline->points;
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*   limit   = vec + outline->n_points;
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points <= 0 )
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.min_ex = ras.max_ex = 0;
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.min_ey = ras.max_ey = 0;
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ex = ras.max_ex = vec->x;
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ey = ras.max_ey = vec->y;
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec++;
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; vec < limit; vec++ )
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TPos  x = vec->x;
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TPos  y = vec->y;
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x < ras.min_ex ) ras.min_ex = x;
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( x > ras.max_ex ) ras.max_ex = x;
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( y < ras.min_ey ) ras.min_ey = y;
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( y > ras.max_ey ) ras.max_ey = y;
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* truncate the bounding box to integer pixels */
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ex = ras.min_ex >> 6;
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.min_ey = ras.min_ey >> 6;
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_ex = ( ras.max_ex + 63 ) >> 6;
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.max_ey = ( ras.max_ey + 63 ) >> 6;
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Record the current cell in the table.                                 */
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static PCell
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_find_cell( RAS_ARG )
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    PCell  *pcell, cell;
566295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TPos    x = ras.ex;
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
5690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( x > ras.count_ex )
5700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      x = ras.count_ex;
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    pcell = &ras.ycells[ras.ey];
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for (;;)
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell = *pcell;
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cell == NULL || cell->x > x )
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        break;
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cell->x == x )
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      pcell = &cell->next;
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.num_cells >= ras.max_cells )
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ft_longjmp( ras.jump_buffer, 1 );
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell        = ras.cells + ras.num_cells++;
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->x     = x;
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->area  = 0;
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->cover = 0;
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    cell->next  = *pcell;
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *pcell      = cell;
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return cell;
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_record_cell( RAS_ARG )
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
604ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( ras.area | ras.cover )
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell  cell = gray_find_cell( RAS_VAR );
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell->area  += ras.area;
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      cell->cover += ras.cover;
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Set the current cell to a new position.                               */
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_set_cell( RAS_ARG_ TCoord  ex,
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                          TCoord  ey )
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Move the cell pointer to a new position.  We set the `invalid'      */
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* flag to indicate that the cell isn't part of those we're interested */
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* in during the render phase.  This means that:                       */
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* . the new vertical position must be within min_ey..max_ey-1.        */
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* . the new horizontal position must be strictly less than max_ex     */
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                                     */
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Note that if a cell is to the left of the clipping region, it is    */
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* actually set to the (min_ex-1) horizontal position.                 */
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* All cells that are on the left of the clipping region go to the */
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* min_ex - 1 horizontal position.                                 */
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey -= ras.min_ey;
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex > ras.max_ex )
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = ras.max_ex;
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex -= ras.min_ex;
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex < 0 )
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = -1;
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* are we moving to a different cell ? */
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex != ras.ex || ey != ras.ey )
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* record the current one if it is valid */
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !ras.invalid )
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_record_cell( RAS_VAR );
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  = 0;
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover = 0;
653ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      ras.ex    = ex;
654ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      ras.ey    = ey;
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
657fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey ||
658fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                  ex >= ras.count_ex               );
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Start a new contour at a given cell.                                  */
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_start_cell( RAS_ARG_ TCoord  ex,
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                            TCoord  ey )
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex > ras.max_ex )
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = (TCoord)( ras.max_ex );
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex < ras.min_ex )
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ex = (TCoord)( ras.min_ex - 1 );
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.area    = 0;
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover   = 0;
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ex      = ex - ras.min_ex;
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.ey      = ey - ras.min_ey;
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.last_ey = SUBPIXELS( ey );
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid = 0;
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ ex, ey );
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Render a scanline as one or more cells.                               */
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_scanline( RAS_ARG_ TCoord  ey,
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TPos    x1,
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TCoord  y1,
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TPos    x2,
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                 TCoord  y2 )
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
698727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    TCoord  ex1, ex2, fx1, fx2, delta, mod;
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long    p, first, dx;
700295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    int     incr;
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dx = x2 - x1;
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex1 = TRUNC( x1 );
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex2 = TRUNC( x2 );
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* trivial case.  Happens often */
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( y1 == y2 )
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gray_set_cell( RAS_VAR_ ex2, ey );
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* everything is located in a single cell.  That is easy! */
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                        */
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex1 == ex2 )
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = y2 - y1;
722295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      ras.area  += (TArea)(( fx1 + fx2 ) * delta);
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* ok, we'll have to render a run of adjacent cells on the same */
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* scanline...                                                  */
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                              */
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = ONE_PIXEL;
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr  = 1;
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx < 0 )
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = fx1 * ( y2 - y1 );
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = 0;
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      incr  = -1;
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dx    = -dx;
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    FT_DIV_MOD( TCoord, p, dx, delta, mod );
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
744295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    ras.area  += (TArea)(( fx1 + first ) * delta);
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover += delta;
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ex1 += incr;
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ ex1, ey );
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y1  += delta;
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ex1 != ex2 )
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
753727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      TCoord  lift, rem;
754727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
755727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
756ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      p = ONE_PIXEL * ( y2 - y1 + delta );
757ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_DIV_MOD( TCoord, p, dx, lift, rem );
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod -= (int)dx;
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ex1 != ex2 )
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = lift;
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mod  += rem;
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mod >= 0 )
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          mod -= (TCoord)dx;
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta++;
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        ras.area  += (TArea)(ONE_PIXEL * delta);
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.cover += delta;
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        y1        += delta;
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ex1       += incr;
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_set_cell( RAS_VAR_ ex1, ey );
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    delta      = y2 - y1;
780295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    ras.area  += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.cover += delta;
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* Render a given line as a series of scanlines.                         */
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_line( RAS_ARG_ TPos  to_x,
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                             TPos  to_y )
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
793295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    TCoord  ey1, ey2, fy1, fy2, mod;
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos    dx, dy, x, x2;
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    long    p, first;
796295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    int     delta, rem, lift, incr;
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey1 = TRUNC( ras.last_ey );
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fy1 = (TCoord)( ras.y - ras.last_ey );
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dx = to_x - ras.x;
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dy = to_y - ras.y;
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* perform vertical clipping */
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  min, max;
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      min = ey1;
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      max = ey2;
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ey1 > ey2 )
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        min = ey2;
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = ey1;
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( min >= ras.max_ey || max < ras.min_ey )
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto End;
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* everything is on a single scanline */
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ey1 == ey2 )
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto End;
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* vertical line - avoid calling gray_render_scanline */
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr = 1;
832049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
833049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx == 0 )
834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  ex     = TRUNC( ras.x );
836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
837295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      TArea   area;
838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = ONE_PIXEL;
841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( dy < 0 )
842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        first = 0;
844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        incr  = -1;
845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = (int)( first - fy1 );
848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  += (TArea)two_fx * delta;
849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ey1       += incr;
851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
852295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      gray_set_cell( RAS_VAR_ ex, ey1 );
853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta = (int)( first + first - ONE_PIXEL );
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      area  = (TArea)two_fx * delta;
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ey1 != ey2 )
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.area  += area;
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.cover += delta;
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ey1       += incr;
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
862295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        gray_set_cell( RAS_VAR_ ex, ey1 );
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta      = (int)( fy2 - ONE_PIXEL + first );
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.area  += (TArea)two_fx * delta;
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.cover += delta;
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      goto End;
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* ok, we have to render several scanlines */
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p     = ( ONE_PIXEL - fy1 ) * dx;
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = ONE_PIXEL;
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    incr  = 1;
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dy < 0 )
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = fy1 * dx;
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = 0;
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      incr  = -1;
882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dy    = -dy;
883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
885ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    FT_DIV_MOD( int, p, dy, delta, mod );
886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = ras.x + delta;
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ey1 += incr;
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ey1 != ey2 )
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      p     = ONE_PIXEL * dx;
896ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      FT_DIV_MOD( int, p, dy, lift, rem );
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      mod -= (int)dy;
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( ey1 != ey2 )
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        delta = lift;
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        mod  += rem;
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( mod >= 0 )
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          mod -= (int)dy;
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          delta++;
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x2 = x + delta;
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_render_scanline( RAS_VAR_ ey1, x,
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       (TCoord)( ONE_PIXEL - first ), x2,
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                       (TCoord)first );
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x = x2;
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ey1 += incr;
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_render_scanline( RAS_VAR_ ey1, x,
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   (TCoord)( ONE_PIXEL - first ), to_x,
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   fy2 );
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  End:
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.x       = to_x;
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.y       = to_y;
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.last_ey = SUBPIXELS( ey2 );
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_split_conic( FT_Vector*  base )
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  a, b;
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = base[2].x;
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x;
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].x = ( base[2].x + b ) / 2;
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].x = ( base[0].x + b ) / 2;
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = ( a + b ) / 2;
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = base[2].y;
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y;
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    a = base[3].y = ( base[2].y + b ) / 2;
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    b = base[1].y = ( base[0].y + b ) / 2;
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = ( a + b ) / 2;
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_conic( RAS_ARG_ const FT_Vector*  control,
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  to )
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos        dx, dy;
956bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    TPos        min, max, y;
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int         top, level;
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int*        levels;
959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
96241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    levels = ras.lev_stack;
96341371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier
9647f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc      = ras.bez_stack;
9657f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[0].x = UPSCALE( to->x );
9667f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[0].y = UPSCALE( to->y );
9677f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[1].x = UPSCALE( control->x );
9687f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[1].y = UPSCALE( control->y );
9697f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[2].x = ras.x;
9707f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    arc[2].y = ras.y;
971bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    top      = 0;
9727f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
9737f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
9747f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx < dy )
976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      dx = dy;
977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
978bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( dx < ONE_PIXEL / 4 )
979bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      goto Draw;
980bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
981bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    /* short-cut the arc that crosses the current band */
982bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    min = max = arc[0].y;
983bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
984bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    y = arc[1].y;
985bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y < min ) min = y;
986bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y > max ) max = y;
987bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
988bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    y = arc[2].y;
989bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y < min ) min = y;
990bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y > max ) max = y;
991bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
992bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
993bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      goto Draw;
994bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly
9957f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    level = 0;
996bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    do
997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
9987f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      dx >>= 2;
9997f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      level++;
1000bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    } while ( dx > ONE_PIXEL / 4 );
1001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    levels[0] = level;
1003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1004aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    do
1005049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      level = levels[top];
1007bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      if ( level > 0 )
1008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_split_conic( arc );
1010049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        arc += 2;
1011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        top++;
1012049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        levels[top] = levels[top - 1] = level - 1;
1013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        continue;
1014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Draw:
10177f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
10187f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      top--;
10197f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      arc -= 2;
1020049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1021aeb407daf3711a10a27f3bc2223c5eb05158076eDavid 'Digit' Turner    } while ( top >= 0 );
1022049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1023049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1024049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1026049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_split_cubic( FT_Vector*  base )
1027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  a, b, c, d;
1029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1030049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1031049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].x = base[3].x;
1032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].x;
1033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].x;
1034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].x = a = ( base[0].x + c ) / 2;
1035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].x = b = ( base[3].x + d ) / 2;
1036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
1037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].x = a = ( a + c ) / 2;
1038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].x = b = ( b + c ) / 2;
1039049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].x = ( a + b ) / 2;
1040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[6].y = base[3].y;
1042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = base[1].y;
1043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    d = base[2].y;
1044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[1].y = a = ( base[0].y + c ) / 2;
1045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[5].y = b = ( base[3].y + d ) / 2;
1046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    c = ( c + d ) / 2;
1047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[2].y = a = ( a + c ) / 2;
1048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[4].y = b = ( b + c ) / 2;
1049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base[3].y = ( a + b ) / 2;
1050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_cubic( RAS_ARG_ const FT_Vector*  control1,
1055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  control2,
1056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                              const FT_Vector*  to )
1057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1058049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  arc;
1059bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    TPos        min, max, y;
1060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc      = ras.bez_stack;
1063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0].x = UPSCALE( to->x );
1064049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[0].y = UPSCALE( to->y );
1065049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1].x = UPSCALE( control2->x );
1066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[1].y = UPSCALE( control2->y );
1067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2].x = UPSCALE( control1->x );
1068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[2].y = UPSCALE( control1->y );
1069049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[3].x = ras.x;
1070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arc[3].y = ras.y;
1071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1072bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    /* Short-cut the arc that crosses the current band. */
1073bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    min = max = arc[0].y;
1074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1075bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    y = arc[1].y;
1076bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y < min )
1077bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      min = y;
1078bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y > max )
1079bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      max = y;
1080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1081bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    y = arc[2].y;
1082bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y < min )
1083bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      min = y;
1084bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y > max )
1085bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      max = y;
1086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1087bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    y = arc[3].y;
1088bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y < min )
1089bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      min = y;
1090bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( y > max )
1091bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      max = y;
1092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1093bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
1094bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly      goto Draw;
10957f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
1096bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    for (;;)
1097bff90fb5ec88ad7fdfb6d1d2f5a5719c20a2c5dcOlivier Bailly    {
10987f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      /* Decide whether to split or draw. See `Rapid Termination          */
10997f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
11007f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      /* F. Hain, at                                                      */
11017f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
11027f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11037f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      {
11047f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        TPos  dx, dy, dx_, dy_;
11057f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        TPos  dx1, dy1, dx2, dy2;
11067f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        TPos  L, s, s_limit;
11077f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11087f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11097f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* dx and dy are x and y components of the P0-P3 chord vector. */
1110fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        dx = dx_ = arc[3].x - arc[0].x;
1111fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        dy = dy_ = arc[3].y - arc[0].y;
1112fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1113fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki        L = FT_HYPOT( dx_, dy_ );
11147f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11157f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* Avoid possible arithmetic overflow below by splitting. */
11167f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        if ( L > 32767 )
11177f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner          goto Split;
11187f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11197f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
11207f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        s_limit = L * (TPos)( ONE_PIXEL / 6 );
11217f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11227f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
11237f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        dx1 = arc[1].x - arc[0].x;
11247f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        dy1 = arc[1].y - arc[0].y;
11257f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        s = FT_ABS( dy * dx1 - dx * dy1 );
11267f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11277f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        if ( s > s_limit )
11287f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner          goto Split;
11297f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11307f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
11317f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        dx2 = arc[2].x - arc[0].x;
11327f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        dy2 = arc[2].y - arc[0].y;
11337f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        s = FT_ABS( dy * dx2 - dx * dy2 );
11347f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11357f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        if ( s > s_limit )
11367f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner          goto Split;
11377f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
1138727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        /* Split super curvy segments where the off points are so far
1139727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease           from the chord that the angles P0-P1-P3 or P0-P2-P3 become
1140727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease           acute as detected by appropriate dot products. */
1141727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
1142727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease             dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
11437f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner          goto Split;
11447f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11457f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        /* No reason to split. */
11467f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        goto Draw;
1147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
11497f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    Split:
11507f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      gray_split_cubic( arc );
11517f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      arc += 3;
11527f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      continue;
1153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
11547f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    Draw:
11557f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
11567f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11577f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      if ( arc == ras.bez_stack )
11587f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner        return;
11597f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner
11607f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner      arc -= 3;
11617f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner    }
11627f08cbd7d6dcf19b8d8e4328e33032aee342e3b4David 'Digit' Turner  }
1163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_move_to( const FT_Vector*  to,
116741371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier                gray_PWorker      worker )
1168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  x, y;
1170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* record current cell, if any */
1173ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease    if ( !ras.invalid )
1174ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      gray_record_cell( RAS_VAR );
1175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* start to a new position */
1177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = UPSCALE( to->x );
1178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y = UPSCALE( to->y );
1179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1180295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
1181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    worker->x = x;
1183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    worker->y = y;
1184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_line_to( const FT_Vector*  to,
119041371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier                gray_PWorker      worker )
1191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1192295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
1193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_conic_to( const FT_Vector*  control,
1199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  to,
120041371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier                 gray_PWorker      worker )
1201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1202295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_conic( RAS_VAR_ control, to );
1203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_cubic_to( const FT_Vector*  control1,
1209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  control2,
1210049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 const FT_Vector*  to,
121141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier                 gray_PWorker      worker )
1212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1213295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    gray_render_cubic( RAS_VAR_ control1, control2, to );
1214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_render_span( int             y,
1220049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    int             count,
1221049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    const FT_Span*  spans,
122241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier                    gray_PWorker    worker )
1223049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    unsigned char*  p;
1225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Bitmap*      map = &worker->target;
1226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* first of all, compute the scanline offset */
1229049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    p = (unsigned char*)map->buffer - y * map->pitch;
1230049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( map->pitch >= 0 )
1231fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      p += ( map->rows - 1 ) * (unsigned int)map->pitch;
1232049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1233049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( ; count > 0; count--, spans++ )
1234049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1235049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      unsigned char  coverage = spans->coverage;
1236049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1237049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1238049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage )
1239049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1240049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* For small-spans it is faster to do it by ourselves than
1241049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         * calling `memset'.  This is mainly due to the cost of the
1242049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         * function call.
1243049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         */
1244049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( spans->len >= 8 )
1245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
1246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1248049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          unsigned char*  q = p + spans->x;
1249049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1250049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1251049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          switch ( spans->len )
1252049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1253049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 7: *q++ = (unsigned char)coverage;
1254049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 6: *q++ = (unsigned char)coverage;
1255049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 5: *q++ = (unsigned char)coverage;
1256049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 4: *q++ = (unsigned char)coverage;
1257049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 3: *q++ = (unsigned char)coverage;
1258049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 2: *q++ = (unsigned char)coverage;
1259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          case 1: *q   = (unsigned char)coverage;
1260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          default:
1261049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ;
1262049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1263049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1264049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1266049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1268049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1269049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1270049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_hline( RAS_ARG_ TCoord  x,
1271049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       TCoord  y,
1272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       TPos    area,
1273295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner                       TCoord  acount )
1274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1275727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    int  coverage;
1276049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1277049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1278049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute the coverage line's coverage, depending on the    */
1279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* outline fill rule                                         */
1280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                           */
1281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
1282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /*                                                           */
1283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
1284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                                    /* use range 0..256 */
1285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( coverage < 0 )
1286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      coverage = -coverage;
1287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
1289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      coverage &= 511;
1291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage > 256 )
1293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 512 - coverage;
1294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else if ( coverage == 256 )
1295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 255;
1296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* normal non-zero winding rule */
1300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( coverage >= 256 )
1301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        coverage = 255;
1302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y += (TCoord)ras.min_ey;
1305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x += (TCoord)ras.min_ex;
1306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
13080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( x >= 32767 )
1309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      x = 32767;
1310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1311295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    /* FT_Span.y is an integer, so limit our coordinates appropriately */
1312295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if ( y >= FT_INT_MAX )
1313295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      y = FT_INT_MAX;
1314295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
1315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( coverage )
1316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1317727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_Span*  span;
1318727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      int       count;
1319727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1320727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* see whether we can add this span to the current list */
1322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      count = ras.num_gray_spans;
1323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span  = ras.gray_spans + count - 1;
1324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( count > 0                          &&
1325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           ras.span_y == y                    &&
1326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           (int)span->x + span->len == (int)x &&
1327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           span->coverage == coverage         )
1328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span->len = (unsigned short)( span->len + acount );
1330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return;
1331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
1334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( ras.render_span && count > 0 )
1336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.render_span( ras.span_y, count, ras.gray_spans,
1337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                           ras.render_span_data );
1338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13410a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        if ( count > 0 )
1342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          int  n;
1344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13460a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE7(( "y = %3d ", ras.span_y ));
1347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          span = ras.gray_spans;
1348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( n = 0; n < count; n++, span++ )
13490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE7(( "[%d..%d]:%02x ",
13500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        span->x, span->x + span->len - 1, span->coverage ));
13510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE7(( "\n" ));
1352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13540a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* FT_DEBUG_LEVEL_TRACE */
1355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.num_gray_spans = 0;
1357295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        ras.span_y         = (int)y;
1358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span  = ras.gray_spans;
1360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
1362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        span++;
1363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* add a gray span to the current list */
1365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->x        = (short)x;
1366049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->len      = (unsigned short)acount;
1367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      span->coverage = (unsigned char)coverage;
1368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.num_gray_spans++;
1370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13740a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* to be called while in the debugger --                                */
13770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* this function causes a compiler warning since it is unused otherwise */
13780a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  static void
1379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_dump_cells( RAS_ARG )
1380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  yindex;
1382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( yindex = 0; yindex < ras.ycount; yindex++ )
1385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell  cell;
1387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      printf( "%3d:", yindex );
1390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
1392295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
1393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      printf( "\n" );
1394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
13970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#endif /* FT_DEBUG_LEVEL_TRACE */
1398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
1401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
1402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int  yindex;
1404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( target );
1406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.num_cells == 0 )
1409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
1410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_gray_spans = 0;
1412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
14130a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE7(( "gray_sweep: start\n" ));
14140a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( yindex = 0; yindex < ras.ycount; yindex++ )
1416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      PCell   cell  = ras.ycells[yindex];
1418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  cover = 0;
1419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      TCoord  x     = 0;
1420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      for ( ; cell != NULL; cell = cell->next )
1423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1424295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        TPos  area;
1425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( cell->x > x && cover != 0 )
1428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
1429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      cell->x - x );
1430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        cover += cell->cover;
1432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        area   = cover * ( ONE_PIXEL * 2 ) - cell->area;
1433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( area != 0 && cell->x >= 0 )
1435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
1436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x = cell->x + 1;
1438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( cover != 0 )
1441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
1442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    ras.count_ex - x );
1443049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.render_span && ras.num_gray_spans > 0 )
1446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span( ras.span_y, ras.num_gray_spans,
1447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                       ras.gray_spans, ras.render_span_data );
14480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1449727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#ifdef FT_DEBUG_LEVEL_TRACE
1450727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1451727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( ras.num_gray_spans > 0 )
1452727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    {
1453727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_Span*  span;
1454727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      int       n;
1455727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1456727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1457727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_TRACE7(( "y = %3d ", ras.span_y ));
1458727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      span = ras.gray_spans;
1459727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
1460727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        FT_TRACE7(( "[%d..%d]:%02x ",
1461727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease                    span->x, span->x + span->len - 1, span->coverage ));
1462727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      FT_TRACE7(( "\n" ));
1463727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
1464727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
14650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE7(( "gray_sweep: end\n" ));
1466727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1467727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#endif /* FT_DEBUG_LEVEL_TRACE */
1468727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
1469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef _STANDALONE_
1473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*  The following function should only compile in stand-alone mode,      */
1477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*  i.e., when building this component without the rest of FreeType.     */
1478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*************************************************************************/
1482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Function>                                                            */
1484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    FT_Outline_Decompose                                               */
1485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Description>                                                         */
14870a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    Walk over an outline's structure to decompose it into individual   */
14880a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    segments and Bézier arcs.  This function is also able to emit      */
1489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    `move to' and `close to' operations to indicate the start and end  */
1490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    of new contours in the outline.                                    */
1491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Input>                                                               */
1493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    outline        :: A pointer to the source target.                  */
1494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14950a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /*    func_interface :: A table of `emitters', i.e., function pointers   */
1496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      called during decomposition to indicate path     */
1497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      operations.                                      */
1498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
14990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /* <InOut>                                                               */
1500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    user           :: A typeless pointer which is passed to each       */
1501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      emitter during the decomposition.  It can be     */
1502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      used to store the state during the               */
1503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                      decomposition.                                   */
1504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
1505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* <Return>                                                              */
1506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*    Error code.  0 means success.                                      */
1507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /*                                                                       */
15080a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  static int
15090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  FT_Outline_Decompose( const FT_Outline*        outline,
15100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        const FT_Outline_Funcs*  func_interface,
15110a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        void*                    user )
1512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#undef SCALED
1514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define SCALED( x )  ( ( (x) << shift ) - delta )
1515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_last;
1517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_control;
1518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector   v_start;
1519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  point;
1521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector*  limit;
1522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char*       tags;
1523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15240a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    int         error;
15250a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int   n;         /* index of contour in outline     */
1527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    int   first;     /* index of first point in contour */
1528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    char  tag;       /* current point's state           */
1529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    int   shift;
15310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    TPos  delta;
1532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1534fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( !outline )
1535fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      return FT_THROW( Invalid_Outline );
1536fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1537fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( !func_interface )
1538727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
15390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
15400a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    shift = func_interface->shift;
15410a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    delta = func_interface->delta;
1542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    first = 0;
1543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1544049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < outline->n_contours; n++ )
1545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      int  last;  /* index of last point in contour */
1547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
15500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      last  = outline->contours[n];
15520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      if ( last < 0 )
15530a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        goto Invalid_Outline;
1554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      limit = outline->points + last;
1555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15560a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_start   = outline->points[first];
1557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_start.x = SCALED( v_start.x );
1558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_start.y = SCALED( v_start.y );
1559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15600a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last   = outline->points[last];
15610a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.x = SCALED( v_last.x );
15620a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      v_last.y = SCALED( v_last.y );
1563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      v_control = v_start;
1565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      point = outline->points + first;
15670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      tags  = outline->tags   + first;
1568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      tag   = FT_CURVE_TAG( tags[0] );
1569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* A contour cannot start with a cubic control point! */
1571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CUBIC )
1572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Invalid_Outline;
1573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* check first point to determine origin */
1575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( tag == FT_CURVE_TAG_CONIC )
1576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* first point is conic control.  Yes, this happens. */
1578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
1579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at last point if it is on the curve */
1581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start = v_last;
1582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          limit--;
1583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else
1585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* if both first and last points are conic,         */
1587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* start at their middle and record its position    */
1588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          /* for closure                                      */
1589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.x = ( v_start.x + v_last.x ) / 2;
1590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_start.y = ( v_start.y + v_last.y ) / 2;
1591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          v_last = v_start;
1593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point--;
1595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags--;
1596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
15980a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  move to (%.2f, %.2f)\n",
15990a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
1600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->move_to( &v_start, user );
1601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( point < limit )
1605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        point++;
1607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tags++;
1608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tag = FT_CURVE_TAG( tags[0] );
1610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        switch ( tag )
1611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_ON:  /* emit a single line_to */
1613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec;
1615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.x = SCALED( point->x );
1618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec.y = SCALED( point->y );
1619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  line to (%.2f, %.2f)\n",
16210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec.x / 64.0, vec.y / 64.0 ));
1622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->line_to( &vec, user );
1623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( error )
1624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Exit;
1625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue;
1626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
16290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          v_control.x = SCALED( point->x );
16300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          v_control.y = SCALED( point->y );
1631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project        Do_Conic:
16330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          if ( point < limit )
16340a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          {
16350a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_Vector  vec;
16360a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_Vector  v_middle;
1637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16390a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            point++;
16400a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            tags++;
16410a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            tag = FT_CURVE_TAG( tags[0] );
1642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16430a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec.x = SCALED( point->x );
16440a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            vec.y = SCALED( point->y );
1645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16460a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( tag == FT_CURVE_TAG_ON )
16470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            {
16480a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  conic to (%.2f, %.2f)"
16490a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with control (%.2f, %.2f)\n",
16500a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
16510a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          v_control.x / 64.0, v_control.y / 64.0 ));
16520a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              error = func_interface->conic_to( &v_control, &vec, user );
1653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
1654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
16550a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              continue;
1656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16580a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( tag != FT_CURVE_TAG_CONIC )
16590a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              goto Invalid_Outline;
16600a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16610a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_middle.x = ( v_control.x + vec.x ) / 2;
16620a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_middle.y = ( v_control.y + vec.y ) / 2;
16630a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16640a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  conic to (%.2f, %.2f)"
16650a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with control (%.2f, %.2f)\n",
16660a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_middle.x / 64.0, v_middle.y / 64.0,
16670a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_control.x / 64.0, v_control.y / 64.0 ));
16680a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            error = func_interface->conic_to( &v_control, &v_middle, user );
16690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            if ( error )
16700a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              goto Exit;
16710a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
16720a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            v_control = vec;
16730a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            goto Do_Conic;
1674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
16760a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          FT_TRACE5(( "  conic to (%.2f, %.2f)"
16770a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      " with control (%.2f, %.2f)\n",
16780a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_start.x / 64.0, v_start.y / 64.0,
16790a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                      v_control.x / 64.0, v_control.y / 64.0 ));
16800a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          error = func_interface->conic_to( &v_control, &v_start, user );
16810a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project          goto Close;
16820a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        default:  /* FT_CURVE_TAG_CUBIC */
1684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {
1685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Vector  vec1, vec2;
1686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point + 1 > limit                             ||
1689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              goto Invalid_Outline;
1691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            point += 2;
1693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tags  += 2;
1694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec1.x = SCALED( point[-2].x );
1696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec1.y = SCALED( point[-2].y );
1697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec2.x = SCALED( point[-1].x );
1699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            vec2.y = SCALED( point[-1].y );
1700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if ( point <= limit )
1702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {
1703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              FT_Vector  vec;
1704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.x = SCALED( point->x );
1707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              vec.y = SCALED( point->y );
1708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
17090a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project              FT_TRACE5(( "  cubic to (%.2f, %.2f)"
17100a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
17110a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec.x / 64.0, vec.y / 64.0,
17120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec1.x / 64.0, vec1.y / 64.0,
17130a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                          vec2.x / 64.0, vec2.y / 64.0 ));
1714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
1715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              if ( error )
1716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                goto Exit;
1717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              continue;
1718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            }
1719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
17200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project            FT_TRACE5(( "  cubic to (%.2f, %.2f)"
17210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
17220a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        v_start.x / 64.0, v_start.y / 64.0,
17230a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec1.x / 64.0, vec1.y / 64.0,
17240a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                        vec2.x / 64.0, vec2.y / 64.0 ));
1725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
1726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto Close;
1727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          }
1728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* close the contour with a line segment */
17320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      FT_TRACE5(( "  line to (%.2f, %.2f)\n",
17330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project                  v_start.x / 64.0, v_start.y / 64.0 ));
1734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = func_interface->line_to( &v_start, user );
1735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project   Close:
1737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( error )
1738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        goto Exit;
1739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      first = last + 1;
1741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
17430a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
1744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Exit:
17470a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
1748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  Invalid_Outline:
1751727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return FT_THROW( Invalid_Outline );
1752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif /* _STANDALONE_ */
1755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
175741371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  typedef struct  gray_TBand_
1758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    TPos  min, max;
1760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
176141371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  } gray_TBand;
1762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1763fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1764fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  FT_DEFINE_OUTLINE_FUNCS(
1765fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    func_interface,
1766fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1767fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Outline_MoveTo_Func) gray_move_to,
1768fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Outline_LineTo_Func) gray_line_to,
1769fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Outline_ConicTo_Func)gray_conic_to,
1770fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Outline_CubicTo_Func)gray_cubic_to,
1771fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    0,
1772fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    0 )
1773fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1774295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
1775295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  static int
1776295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  gray_convert_glyph_inner( RAS_ARG )
1777295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner  {
1778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    volatile int  error = 0;
1780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1781295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#ifdef FT_CONFIG_OPTION_PIC
1782295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      FT_Outline_Funcs func_interface;
1783295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner      Init_Class_func_interface(&func_interface);
1784295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner#endif
17850a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
1786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ft_setjmp( ras.jump_buffer ) == 0 )
1787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
1789ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease      if ( !ras.invalid )
1790ec0bab5697bb31ba980810145f62e3799946ec60Victoria Lease        gray_record_cell( RAS_VAR );
1791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1793727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      error = FT_THROW( Memory_Overflow );
1794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
1796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
1800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_convert_glyph( RAS_ARG )
1801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
180241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    gray_TBand            bands[40];
180341371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    gray_TBand* volatile  band;
180441371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    int volatile          n, num_bands;
180541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    TPos volatile         min, max, max_y;
180641371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    FT_BBox*              clip;
1807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* Set up state in the raster object */
1810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    gray_compute_cbox( RAS_VAR );
1811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* clip to target bitmap, exit if nothing to do */
1813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    clip = &ras.clip_box;
1814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
1816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project         ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
1817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
1820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
1821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
1823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
1824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.count_ex = ras.max_ex - ras.min_ex;
1826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.count_ey = ras.max_ey - ras.min_ey;
1827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18280a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    /* set up vertical bands */
1829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
18300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( num_bands == 0 )
18310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      num_bands = 1;
18320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( num_bands >= 39 )
18330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      num_bands = 39;
1834049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1835049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.band_shoot = 0;
1836049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1837049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    min   = ras.min_ey;
1838049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    max_y = ras.max_ey;
1839049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1840049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for ( n = 0; n < num_bands; n++, min = max )
1841049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1842049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      max = min + ras.band_size;
1843049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( n == num_bands - 1 || max > max_y )
1844049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        max = max_y;
1845049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1846049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      bands[0].min = min;
1847049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      bands[0].max = max;
1848049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      band         = bands;
1849049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1850049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      while ( band >= bands )
1851049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
1852049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        TPos  bottom, top, middle;
1853049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        int   error;
1854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          PCell  cells_max;
1857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          int    yindex;
1858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          long   cell_start, cell_end, cell_mod;
1859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.ycells = (PCell*)ras.buffer;
1862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.ycount = band->max - band->min;
1863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1864fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          cell_start = (long)sizeof ( PCell ) * ras.ycount;
1865fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          cell_mod   = cell_start % (long)sizeof ( TCell );
1866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( cell_mod > 0 )
1867fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki            cell_start += (long)sizeof ( TCell ) - cell_mod;
1868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cell_end  = ras.buffer_size;
1870fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki          cell_end -= cell_end % (long)sizeof ( TCell );
1871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          cells_max = (PCell)( (char*)ras.buffer + cell_end );
1873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.cells = (PCell)( (char*)ras.buffer + cell_start );
1874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ras.cells >= cells_max )
1875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto ReduceBands;
1876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.max_cells = cells_max - ras.cells;
1878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          if ( ras.max_cells < 2 )
1879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            goto ReduceBands;
1880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          for ( yindex = 0; yindex < ras.ycount; yindex++ )
1882049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ras.ycells[yindex] = NULL;
1883049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1884049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1885049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.num_cells = 0;
1886049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.invalid   = 1;
1887049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.min_ey    = band->min;
1888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.max_ey    = band->max;
1889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ras.count_ey  = band->max - band->min;
1890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        error = gray_convert_glyph_inner( RAS_VAR );
1892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( !error )
1894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
1895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          gray_sweep( RAS_VAR_ &ras.target );
1896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          band--;
1897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          continue;
1898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else if ( error != ErrRaster_Memory_Overflow )
1900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 1;
1901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ReduceBands:
1903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* render pool overflow; we will reduce the render band by half */
1904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        bottom = band->min;
1905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        top    = band->max;
1906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        middle = bottom + ( ( top - bottom ) >> 1 );
1907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* This is too complex for a single scanline; there must */
1909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        /* be some problems.                                     */
1910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( middle == bottom )
1911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {
19120a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project#ifdef FT_DEBUG_LEVEL_TRACE
1913295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner          FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
1914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#endif
1915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          return 1;
1916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        }
1917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if ( bottom-top >= ras.band_size )
1919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          ras.band_shoot++;
1920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[1].min = bottom;
1922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[1].max = middle;
1923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[0].min = middle;
1924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band[0].max = top;
1925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        band++;
1926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
1927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( ras.band_shoot > 8 && ras.band_size > 16 )
1930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.band_size = ras.band_size / 2;
1931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
1933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
1934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
193741371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier  gray_raster_render( gray_PRaster             raster,
1938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      const FT_Raster_Params*  params )
1939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
1940fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    const FT_Outline*  outline     = (const FT_Outline*)params->source;
1941fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    const FT_Bitmap*   target_map  = params->target;
1942fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1943fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    gray_TWorker  worker[1];
1944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1945fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    TCell  buffer[FT_MAX( FT_RENDER_POOL_SIZE, 2048 ) / sizeof ( TCell )];
1946fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    long   buffer_size = sizeof ( buffer );
1947fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    int    band_size   = (int)( buffer_size /
1948fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                                (long)( sizeof ( TCell ) * 8 ) );
1949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1950fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
1951fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    if ( !raster )
1952727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Argument );
1953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline )
1955727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Outline );
1956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* return immediately if the outline is empty */
1958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points == 0 || outline->n_contours <= 0 )
1959049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
1960049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1961049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !outline->contours || !outline->points )
1962727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Outline );
1963049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1964049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( outline->n_points !=
1965049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project           outline->contours[outline->n_contours - 1] + 1 )
1966727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Outline );
1967049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1968049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* if direct mode is not set, we must have a target bitmap */
19690a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
1970049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1971049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map )
1972727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        return FT_THROW( Invalid_Argument );
1973049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1974049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* nothing to do */
1975049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map->width || !target_map->rows )
1976049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return 0;
1977049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1978049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( !target_map->buffer )
1979727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        return FT_THROW( Invalid_Argument );
1980049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1981049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1982049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* this version does not support monochrome rendering */
1983049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_AA ) )
1984727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_THROW( Invalid_Mode );
1985049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
1986049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* compute clipping box */
19870a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
1988049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1989049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      /* compute clip box from target pixmap */
1990049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMin = 0;
1991049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMin = 0;
1992fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ras.clip_box.xMax = (FT_Pos)target_map->width;
1993fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki      ras.clip_box.yMax = (FT_Pos)target_map->rows;
1994049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
1995049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( params->flags & FT_RASTER_FLAG_CLIP )
1996049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box = params->clip_box;
1997049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
1998049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
1999049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMin = -32768L;
2000049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMin = -32768L;
2001049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.xMax =  32767L;
2002049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.clip_box.yMax =  32767L;
2003049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2004049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2005fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    gray_init_cells( RAS_VAR_ buffer, buffer_size );
2006049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2007049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.outline        = *outline;
2008049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_cells      = 0;
2009049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.invalid        = 1;
2010fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    ras.band_size      = band_size;
2011049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ras.num_gray_spans = 0;
2012fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    ras.span_y         = 0;
2013049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2014049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( params->flags & FT_RASTER_FLAG_DIRECT )
2015049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2016049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
2017049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      ras.render_span_data = params->user;
2018049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
20190a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    else
20200a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    {
20210a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.target           = *target_map;
20220a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
20230a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project      ras.render_span_data = &ras;
20240a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project    }
2025049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2026295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    return gray_convert_glyph( RAS_VAR );
2027049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2028049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2029049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
20300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
20310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project  /****                         a static object.                   *****/
2032049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2033049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#ifdef _STANDALONE_
2034049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2035049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
2036049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_new( void*       memory,
2037049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Raster*  araster )
2038049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
203941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    static gray_TRaster  the_raster;
2040049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2041049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( memory );
2042049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2043049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2044049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *araster = (FT_Raster)&the_raster;
2045049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
2046049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2047049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return 0;
2048049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2049049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2050049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2051049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2052049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_done( FT_Raster  raster )
2053049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2054049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* nothing */
2055049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_UNUSED( raster );
2056049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2057049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2058aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#else /* !_STANDALONE_ */
2059049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2060049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static int
2061049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_new( FT_Memory   memory,
2062049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                   FT_Raster*  araster )
2063049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
206441371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    FT_Error      error;
206541371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    gray_PRaster  raster = NULL;
2066049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2067049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2068049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *araster = 0;
206941371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
2070049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
2071049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      raster->memory = memory;
207241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier      *araster       = (FT_Raster)raster;
2073049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
2074049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2075049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return error;
2076049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2077049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2078049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2079049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2080049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_done( FT_Raster  raster )
2081049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
208241371e1e39c8528eb0c4bc40683c736e6683e60cEric Vannier    FT_Memory  memory = (FT_Memory)((gray_PRaster)raster)->memory;
2083049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2084049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2085049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_FREE( raster );
2086049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2087049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2088aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich#endif /* !_STANDALONE_ */
2089049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2090049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2091049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
2092049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  gray_raster_reset( FT_Raster  raster,
2093049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     char*      pool_base,
2094049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     long       pool_size )
2095049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
2096fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( raster );
2097fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( pool_base );
2098fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( pool_size );
2099fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  }
2100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2102fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  static int
2103fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  gray_raster_set_mode( FT_Raster      raster,
2104fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        unsigned long  mode,
2105fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki                        void*          args )
2106fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  {
2107fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( raster );
2108fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( mode );
2109fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    FT_UNUSED( args );
2110fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2111fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2112fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    return 0; /* nothing to do */
2113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
2114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2116fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki  FT_DEFINE_RASTER_FUNCS(
2117fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    ft_grays_raster,
2118fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki
2119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_GLYPH_FORMAT_OUTLINE,
2120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_New_Func)     gray_raster_new,
2122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Reset_Func)   gray_raster_reset,
2123fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Raster_Set_Mode_Func)gray_raster_set_mode,
2124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    (FT_Raster_Render_Func)  gray_raster_render,
2125fb6b5b10aaa74b8c8974714b41bac35bdd1c772dMakoto Onuki    (FT_Raster_Done_Func)    gray_raster_done )
2126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
2128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
21290a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
21300a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
21310a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* Local Variables: */
21320a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* coding: utf-8    */
21330a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project/* End:             */
2134