1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* ftgrays.c */ 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* A new `perfect' anti-aliasing renderer (body). */ 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Copyright 2000-2003, 2005-2013 by */ 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* This file is part of the FreeType project, and may only be used, */ 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* modified, and distributed under the terms of the FreeType project */ 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* this file you indicate that you have read the license and */ 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* understand and accept it fully. */ 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/ 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This file can be compiled without the rest of the FreeType engine, by */ 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* defining the _STANDALONE_ macro when compiling it. You also need to */ 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* put the files `ftgrays.h' and `ftimage.h' into the current */ 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compilation directory. Typically, you could do something like */ 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - copy `src/smooth/ftgrays.c' (this file) to your current directory */ 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */ 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* same directory */ 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in */ 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cc -c -D_STANDALONE_ ftgrays.c */ 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The renderer can be initialized with a call to */ 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated */ 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* with a call to `ft_gray_raster.raster_render'. */ 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* See the comments and documentation in the file `ftimage.h' for more */ 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* details on how the raster works. */ 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This is a new anti-aliasing scan-converter for FreeType 2. The */ 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* algorithm used here is _very_ different from the one in the standard */ 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */ 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* coverage of the outline on each pixel cell. */ 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* It is based on ideas that I initially found in Raph Levien's */ 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* excellent LibArt graphics library (see http://www.levien.com/libart */ 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for more information, though the web pages do not tell anything */ 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* about the renderer; you'll have to dive into the source code to */ 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* understand how it works). */ 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Note, however, that this is a _very_ different implementation */ 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compared to Raph's. Coverage information is stored in a very */ 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* different way, and I don't use sorted vector paths. Also, it doesn't */ 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* use floating point values. */ 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This renderer has the following advantages: */ 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - It doesn't need an intermediate bitmap. Instead, one can supply a */ 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* callback function that will be called by the renderer to draw gray */ 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* spans on any target surface. You can thus do direct composition on */ 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* any kind of bitmap, provided that you give the renderer the right */ 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* callback. */ 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */ 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* each pixel cell. */ 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - It performs a single pass on the outline (the `standard' FT2 */ 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* renderer makes two passes). */ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - It can easily be modified to render to _any_ number of gray levels */ 76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* cheaply. */ 77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* - For small (< 20) pixel sizes, it is faster than the standard */ 79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* renderer. */ 80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* messages during execution. */ 89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FT_COMPONENT 91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_COMPONENT trace_smooth 92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _STANDALONE_ 95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Auxiliary macros for token concatenation. */ 98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_ERR_XCAT( x, y ) x ## y 99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_ERR_CAT( x, y ) FT_ERR_XCAT( x, y ) 100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* define this to dump debugging information */ 103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* #define FT_DEBUG_LEVEL_TRACE */ 104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <stdio.h> 108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <stdarg.h> 109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <stddef.h> 112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <string.h> 113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <setjmp.h> 114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <limits.h> 115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_UINT_MAX UINT_MAX 116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_INT_MAX INT_MAX 117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ft_memset memset 119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ft_setjmp setjmp 121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ft_longjmp longjmp 122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ft_jmp_buf jmp_buf 123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef ptrdiff_t FT_PtrDist; 125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ErrRaster_Invalid_Mode -2 128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ErrRaster_Invalid_Outline -1 129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ErrRaster_Invalid_Argument -3 130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ErrRaster_Memory_Overflow -4 131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_BEGIN_HEADER 133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_END_HEADER 134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ftimage.h" 136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ftgrays.h" 137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This macro is used to indicate that a function parameter is unused. */ 140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Its purpose is simply to reduce compiler warnings. Note also that */ 141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* simply defining it as `(void)x' doesn't avoid warnings with certain */ 142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ANSI compilers (e.g. LCC). */ 143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_UNUSED( x ) (x) = (x) 144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */ 147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void 151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Message( const char* fmt, 152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ... ) 153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov va_list ap; 155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov va_start( ap, fmt ); 158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vfprintf( stderr, fmt, ap ); 159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov va_end( ap ); 160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* empty function useful for setting a breakpoint to catch errors */ 164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int 165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Throw( int error, 166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int line, 167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const char* file ) 168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( error ); 170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( line ); 171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( file ); 172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* we don't handle tracing levels in stand-alone mode; */ 178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_TRACE5 179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRACE5( varformat ) FT_Message varformat 180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_TRACE7 182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRACE7( varformat ) FT_Message varformat 183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_ERROR 185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_ERROR( varformat ) FT_Message varformat 186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_THROW( e ) \ 189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( FT_Throw( FT_ERR_CAT( ErrRaster, e ), \ 190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov __LINE__, \ 191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov __FILE__ ) | \ 192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_ERR_CAT( ErrRaster, e ) ) 193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !FT_DEBUG_LEVEL_TRACE */ 195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRACE5( x ) do { } while ( 0 ) /* nothing */ 197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRACE7( x ) do { } while ( 0 ) /* nothing */ 198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_ERROR( x ) do { } while ( 0 ) /* nothing */ 199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_THROW( e ) FT_ERR_CAT( ErrRaster_, e ) 200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !FT_DEBUG_LEVEL_TRACE */ 203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_DEFINE_OUTLINE_FUNCS( class_, \ 206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov move_to_, line_to_, \ 207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov conic_to_, cubic_to_, \ 208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift_, delta_ ) \ 209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static const FT_Outline_Funcs class_ = \ 210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { \ 211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov move_to_, \ 212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov line_to_, \ 213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov conic_to_, \ 214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cubic_to_, \ 215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift_, \ 216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta_ \ 217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, \ 220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_new_, raster_reset_, \ 221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_set_mode_, raster_render_, \ 222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_done_ ) \ 223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Raster_Funcs class_ = \ 224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { \ 225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov glyph_format_, \ 226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_new_, \ 227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_reset_, \ 228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_set_mode_, \ 229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_render_, \ 230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster_done_ \ 231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov }; 232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !_STANDALONE_ */ 235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h" 238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ftgrays.h" 239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftobjs.h" 240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftdebug.h" 241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/ftoutln.h" 242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ftsmerrs.h" 244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "ftspic.h" 246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define Smooth_Err_Invalid_Mode Smooth_Err_Cannot_Render_Glyph 248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define Smooth_Err_Memory_Overflow Smooth_Err_Out_Of_Memory 249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ErrRaster_Memory_Overflow Smooth_Err_Out_Of_Memory 250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !_STANDALONE_ */ 253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_MEM_SET 256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_MEM_SET( d, s, c ) ft_memset( d, s, c ) 257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_MEM_ZERO 260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count ) 261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* as usual, for the speed hungry :-) */ 264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef RAS_ARG 266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef RAS_ARG_ 267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef RAS_VAR 268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef RAS_VAR_ 269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_STATIC_RASTER 271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_ARG gray_PWorker worker 273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_ARG_ gray_PWorker worker, 274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_VAR worker 276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_VAR_ worker, 277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* FT_STATIC_RASTER */ 279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_ARG /* empty */ 281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_ARG_ /* empty */ 282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_VAR /* empty */ 283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define RAS_VAR_ /* empty */ 284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_STATIC_RASTER */ 286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* must be at least 6 bits! */ 289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define PIXEL_BITS 8 290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef FLOOR 292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef CEILING 293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef TRUNC 294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef SCALED 295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ONE_PIXEL ( 1L << PIXEL_BITS ) 297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define PIXEL_MASK ( -1L << PIXEL_BITS ) 298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) ) 299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS ) 300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FLOOR( x ) ( (x) & -ONE_PIXEL ) 301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL ) 302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL ) 303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if PIXEL_BITS >= 6 305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) ) 306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) ) 307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) ) 309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) ) 310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* TYPE DEFINITIONS */ 316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* don't change the following types to FT_Int or FT_Pos, since we might */ 319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* need to define them to "float" or "double" when experimenting with */ 320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* new algorithms */ 321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef long TCoord; /* integer scanline/pixel coordinate */ 323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef long TPos; /* sub-pixel coordinate */ 324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* determine the type used to store cell areas. This normally takes at */ 326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */ 327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `long' instead of `int', otherwise bad things happen */ 328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if PIXEL_BITS <= 7 330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef int TArea; 332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* PIXEL_BITS >= 8 */ 334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* approximately determine the size of integers using an ANSI-C header */ 336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if FT_UINT_MAX == 0xFFFFU 337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef long TArea; 338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef int TArea; 340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* PIXEL_BITS >= 8 */ 343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* maximum number of gray spans in a call to the span callback */ 346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_MAX_GRAY_SPANS 32 347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TCell_* PCell; 350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct TCell_ 352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x; /* same with gray_TWorker.ex */ 354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord cover; /* same with gray_TWorker.cover */ 355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TArea area; 356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell next; 357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } TCell; 359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */ 362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* We disable the warning `structure was padded due to */ 363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* __declspec(align())' in order to compile cleanly with */ 364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the maximum level of warnings. */ 365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#pragma warning( push ) 366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#pragma warning( disable : 4324 ) 367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* _MSC_VER */ 368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct gray_TWorker_ 370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ex, ey; 372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos min_ex, max_ex; 373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos min_ey, max_ey; 374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos count_ex, count_ey; 375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TArea area; 377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord cover; 378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int invalid; 379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell cells; 381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_PtrDist max_cells; 382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_PtrDist num_cells; 383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord cx, cy; 385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x, y; 386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos last_ey; 388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector bez_stack[32 * 3 + 1]; 390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int lev_stack[32]; 391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline outline; 393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bitmap target; 394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox clip_box; 395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Span gray_spans[FT_MAX_GRAY_SPANS]; 397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int num_gray_spans; 398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Raster_Span_Func render_span; 400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* render_span_data; 401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int span_y; 402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int band_size; 404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int band_shoot; 405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_jmp_buf jump_buffer; 407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* buffer; 409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long buffer_size; 410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell* ycells; 412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos ycount; 413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } gray_TWorker, *gray_PWorker; 415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#if defined( _MSC_VER ) 417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#pragma warning( pop ) 418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef FT_STATIC_RASTER 422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define ras (*worker) 423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else 424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static gray_TWorker ras; 425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct gray_TRaster_ 429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* buffer; 431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long buffer_size; 432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int band_size; 433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* memory; 434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker; 435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } gray_TRaster, *gray_PRaster; 437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Initialize the cells table. */ 443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_init_cells( RAS_ARG_ void* buffer, 446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long byte_size ) 447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.buffer = buffer; 449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.buffer_size = byte_size; 450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ycells = (PCell*) buffer; 452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cells = NULL; 453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_cells = 0; 454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_cells = 0; 455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area = 0; 456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover = 0; 457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.invalid = 1; 458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Compute the outline bounding box. */ 464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_compute_cbox( RAS_ARG ) 467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline* outline = &ras.outline; 469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* vec = outline->points; 470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* limit = vec + outline->n_points; 471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_points <= 0 ) 474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ex = ras.max_ex = 0; 476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ey = ras.max_ey = 0; 477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ex = ras.max_ex = vec->x; 481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ey = ras.max_ey = vec->y; 482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec++; 484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; vec < limit; vec++ ) 486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x = vec->x; 488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos y = vec->y; 489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x < ras.min_ex ) ras.min_ex = x; 492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x > ras.max_ex ) ras.max_ex = x; 493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < ras.min_ey ) ras.min_ey = y; 494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > ras.max_ey ) ras.max_ey = y; 495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* truncate the bounding box to integer pixels */ 498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ex = ras.min_ex >> 6; 499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ey = ras.min_ey >> 6; 500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_ex = ( ras.max_ex + 63 ) >> 6; 501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_ey = ( ras.max_ey + 63 ) >> 6; 502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Record the current cell in the table. */ 508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static PCell 510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_find_cell( RAS_ARG ) 511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell *pcell, cell; 513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x = ras.ex; 514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x > ras.count_ex ) 517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = ras.count_ex; 518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pcell = &ras.ycells[ras.ey]; 520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (;;) 521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell = *pcell; 523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cell == NULL || cell->x > x ) 524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov break; 525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cell->x == x ) 527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov pcell = &cell->next; 530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.num_cells >= ras.max_cells ) 533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ft_longjmp( ras.jump_buffer, 1 ); 534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell = ras.cells + ras.num_cells++; 536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->x = x; 537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->area = 0; 538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->cover = 0; 539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->next = *pcell; 541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *pcell = cell; 542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return cell; 545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_record_cell( RAS_ARG ) 550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !ras.invalid && ( ras.area | ras.cover ) ) 552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell cell = gray_find_cell( RAS_VAR ); 554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->area += ras.area; 557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->cover += ras.cover; 558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set the current cell to a new position. */ 565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_ARG_ TCoord ex, 568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ey ) 569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Move the cell pointer to a new position. We set the `invalid' */ 571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* flag to indicate that the cell isn't part of those we're interested */ 572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* in during the render phase. This means that: */ 573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* . the new vertical position must be within min_ey..max_ey-1. */ 575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* . the new horizontal position must be strictly less than max_ex */ 576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Note that if a cell is to the left of the clipping region, it is */ 578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* actually set to the (min_ex-1) horizontal position. */ 579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* All cells that are on the left of the clipping region go to the */ 581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* min_ex - 1 horizontal position. */ 582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey -= ras.min_ey; 583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex > ras.max_ex ) 585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex = ras.max_ex; 586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex -= ras.min_ex; 588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex < 0 ) 589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex = -1; 590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* are we moving to a different cell ? */ 592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex != ras.ex || ey != ras.ey ) 593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* record the current one if it is valid */ 595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !ras.invalid ) 596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_record_cell( RAS_VAR ); 597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area = 0; 599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover = 0; 600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ex = ex; 603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ey = ey; 604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey || 605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex >= ras.count_ex ); 606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Start a new contour at a given cell. */ 612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_start_cell( RAS_ARG_ TCoord ex, 615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ey ) 616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex > ras.max_ex ) 618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex = (TCoord)( ras.max_ex ); 619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex < ras.min_ex ) 621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex = (TCoord)( ras.min_ex - 1 ); 622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area = 0; 624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover = 0; 625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ex = ex - ras.min_ex; 626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ey = ey - ras.min_ey; 627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.last_ey = SUBPIXELS( ey ); 628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.invalid = 0; 629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex, ey ); 631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Render a scanline as one or more cells. */ 637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_scanline( RAS_ARG_ TCoord ey, 640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x1, 641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord y1, 642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x2, 643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord y2 ) 644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ex1, ex2, fx1, fx2, delta, mod; 646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long p, first, dx; 647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int incr; 648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = x2 - x1; 651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex1 = TRUNC( x1 ); 653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex2 = TRUNC( x2 ); 654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); 655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); 656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* trivial case. Happens often */ 658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y1 == y2 ) 659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex2, ey ); 661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* everything is located in a single cell. That is easy! */ 665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex1 == ex2 ) 667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = y2 - y1; 669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)(( fx1 + fx2 ) * delta); 670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ok, we'll have to render a run of adjacent cells on the same */ 675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* scanline... */ 676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 ); 678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = ONE_PIXEL; 679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = 1; 680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx < 0 ) 682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = fx1 * ( y2 - y1 ); 684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = -1; 686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = -dx; 687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = (TCoord)( p / dx ); 690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod = (TCoord)( p % dx ); 691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mod < 0 ) 692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta--; 694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod += (TCoord)dx; 695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)(( fx1 + first ) * delta); 698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex1 += incr; 701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex1, ey ); 702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y1 += delta; 703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ex1 != ex2 ) 705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord lift, rem; 707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = ONE_PIXEL * ( y2 - y1 + delta ); 710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lift = (TCoord)( p / dx ); 711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rem = (TCoord)( p % dx ); 712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( rem < 0 ) 713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lift--; 715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rem += (TCoord)dx; 716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod -= (int)dx; 719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ex1 != ex2 ) 721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = lift; 723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod += rem; 724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mod >= 0 ) 725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod -= (TCoord)dx; 727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta++; 728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)(ONE_PIXEL * delta); 731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y1 += delta; 733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ex1 += incr; 734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex1, ey ); 735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = y2 - y1; 739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)(( fx2 + ONE_PIXEL - first ) * delta); 740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Render a given line as a series of scanlines. */ 747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_line( RAS_ARG_ TPos to_x, 750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos to_y ) 751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ey1, ey2, fy1, fy2, mod; 753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos dx, dy, x, x2; 754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long p, first; 755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int delta, rem, lift, incr; 756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey1 = TRUNC( ras.last_ey ); 759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ 760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fy1 = (TCoord)( ras.y - ras.last_ey ); 761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); 762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = to_x - ras.x; 764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy = to_y - ras.y; 765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* XXX: we should do something about the trivial case where dx == 0, */ 767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* as it happens very often! */ 768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* perform vertical clipping */ 770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord min, max; 772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = ey1; 775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = ey2; 776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ey1 > ey2 ) 777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = ey2; 779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = ey1; 780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( min >= ras.max_ey || max < ras.min_ey ) 782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto End; 783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* everything is on a single scanline */ 786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ey1 == ey2 ) 787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 ); 789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto End; 790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* vertical line - avoid calling gray_render_scanline */ 793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = 1; 794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx == 0 ) 796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord ex = TRUNC( ras.x ); 798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 ); 799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TArea area; 800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = ONE_PIXEL; 803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dy < 0 ) 804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = -1; 807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = (int)( first - fy1 ); 810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)two_fx * delta; 811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey1 += incr; 813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex, ey1 ); 815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = (int)( first + first - ONE_PIXEL ); 817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov area = (TArea)two_fx * delta; 818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ey1 != ey2 ) 819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += area; 821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey1 += incr; 823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ ex, ey1 ); 825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = (int)( fy2 - ONE_PIXEL + first ); 828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.area += (TArea)two_fx * delta; 829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cover += delta; 830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto End; 832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* ok, we have to render several scanlines */ 835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = ( ONE_PIXEL - fy1 ) * dx; 836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = ONE_PIXEL; 837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = 1; 838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dy < 0 ) 840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = fy1 * dx; 842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov incr = -1; 844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy = -dy; 845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = (int)( p / dy ); 848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod = (int)( p % dy ); 849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mod < 0 ) 850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta--; 852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod += (TCoord)dy; 853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = ras.x + delta; 856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first ); 857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey1 += incr; 859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); 860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ey1 != ey2 ) 862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = ONE_PIXEL * dx; 864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lift = (int)( p / dy ); 865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rem = (int)( p % dy ); 866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( rem < 0 ) 867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov lift--; 869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rem += (int)dy; 870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod -= (int)dy; 872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( ey1 != ey2 ) 874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = lift; 876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod += rem; 877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( mod >= 0 ) 878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov mod -= (int)dy; 880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta++; 881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x2 = x + delta; 884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_scanline( RAS_VAR_ ey1, x, 885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TCoord)( ONE_PIXEL - first ), x2, 886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TCoord)first ); 887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = x2; 888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ey1 += incr; 890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 ); 891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_scanline( RAS_VAR_ ey1, x, 895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (TCoord)( ONE_PIXEL - first ), to_x, 896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov fy2 ); 897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov End: 899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.x = to_x; 900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.y = to_y; 901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.last_ey = SUBPIXELS( ey2 ); 902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_split_conic( FT_Vector* base ) 907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos a, b; 909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[4].x = base[2].x; 912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = base[1].x; 913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = base[3].x = ( base[2].x + b ) / 2; 914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = base[1].x = ( base[0].x + b ) / 2; 915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[2].x = ( a + b ) / 2; 916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[4].y = base[2].y; 918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = base[1].y; 919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov a = base[3].y = ( base[2].y + b ) / 2; 920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov b = base[1].y = ( base[0].y + b ) / 2; 921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[2].y = ( a + b ) / 2; 922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_conic( RAS_ARG_ const FT_Vector* control, 927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* to ) 928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos dx, dy; 930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos min, max, y; 931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int top, level; 932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int* levels; 933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* arc; 934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov levels = ras.lev_stack; 937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc = ras.bez_stack; 939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[0].x = UPSCALE( to->x ); 940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[0].y = UPSCALE( to->y ); 941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[1].x = UPSCALE( control->x ); 942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[1].y = UPSCALE( control->y ); 943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[2].x = ras.x; 944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[2].y = ras.y; 945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov top = 0; 946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x ); 948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y ); 949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx < dy ) 950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = dy; 951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx < ONE_PIXEL / 4 ) 953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Draw; 954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* short-cut the arc that crosses the current band */ 956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = max = arc[0].y; 957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = arc[1].y; 959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < min ) min = y; 960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > max ) max = y; 961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = arc[2].y; 963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < min ) min = y; 964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > max ) max = y; 965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) 967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Draw; 968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov level = 0; 970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do 971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx >>= 2; 973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov level++; 974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( dx > ONE_PIXEL / 4 ); 975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov levels[0] = level; 977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov do 979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov level = levels[top]; 981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( level > 0 ) 982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_split_conic( arc ); 984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc += 2; 985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov top++; 986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov levels[top] = levels[top - 1] = level - 1; 987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Draw: 991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); 992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov top--; 993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc -= 2; 994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } while ( top >= 0 ); 996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_split_cubic( FT_Vector* base ) 1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos a, b, c, d; 1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[6].x = base[3].x; 1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c = base[1].x; 1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = base[2].x; 1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[1].x = a = ( base[0].x + c ) / 2; 1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[5].x = b = ( base[3].x + d ) / 2; 1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c = ( c + d ) / 2; 1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[2].x = a = ( a + c ) / 2; 1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[4].x = b = ( b + c ) / 2; 1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[3].x = ( a + b ) / 2; 1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[6].y = base[3].y; 1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c = base[1].y; 1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov d = base[2].y; 1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[1].y = a = ( base[0].y + c ) / 2; 1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[5].y = b = ( base[3].y + d ) / 2; 1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov c = ( c + d ) / 2; 1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[2].y = a = ( a + c ) / 2; 1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[4].y = b = ( b + c ) / 2; 1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov base[3].y = ( a + b ) / 2; 1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_cubic( RAS_ARG_ const FT_Vector* control1, 1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* control2, 1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* to ) 1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* arc; 1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos min, max, y; 1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc = ras.bez_stack; 1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[0].x = UPSCALE( to->x ); 1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[0].y = UPSCALE( to->y ); 1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[1].x = UPSCALE( control2->x ); 1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[1].y = UPSCALE( control2->y ); 1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[2].x = UPSCALE( control1->x ); 1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[2].y = UPSCALE( control1->y ); 1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[3].x = ras.x; 1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc[3].y = ras.y; 1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Short-cut the arc that crosses the current band. */ 1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = max = arc[0].y; 1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = arc[1].y; 1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < min ) 1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = y; 1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > max ) 1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = y; 1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = arc[2].y; 1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < min ) 1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = y; 1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > max ) 1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = y; 1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = arc[3].y; 1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y < min ) 1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = y; 1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y > max ) 1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = y; 1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) 1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Draw; 1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for (;;) 1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Decide whether to split or draw. See `Rapid Termination */ 1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */ 1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* F. Hain, at */ 1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ 1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos dx, dy, dx_, dy_; 1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos dx1, dy1, dx2, dy2; 1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos L, s, s_limit; 1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* dx and dy are x and y components of the P0-P3 chord vector. */ 1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx = arc[3].x - arc[0].x; 1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy = arc[3].y - arc[0].y; 1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* L is an (under)estimate of the Euclidean distance P0-P3. */ 1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated */ 1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* with least maximum error by */ 1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* r_upperbound = dx + (sqrt(2) - 1) * dy , */ 1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */ 1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* error of no more than 8.4%. */ 1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Similarly, some elementary calculus shows that r can be */ 1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* underestimated with least maximum error by */ 1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx */ 1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* + sqrt(2 - sqrt(2)) / 2 * dy . */ 1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* 236/256 and 97/256 are (under)estimates of the two algebraic */ 1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* numbers, giving an error of no more than 8.1%. */ 1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx_ = FT_ABS( dx ); 1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy_ = FT_ABS( dy ); 1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This is the same as */ 1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* L = ( 236 * FT_MAX( dx_, dy_ ) */ 1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */ 1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov L = ( dx_ > dy_ ? 236 * dx_ + 97 * dy_ 1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov : 97 * dx_ + 236 * dy_ ) >> 8; 1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Avoid possible arithmetic overflow below by splitting. */ 1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( L > 32767 ) 1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Split; 1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ 1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov s_limit = L * (TPos)( ONE_PIXEL / 6 ); 1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* s is L * the perpendicular distance from P1 to the line P0-P3. */ 1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx1 = arc[1].x - arc[0].x; 1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy1 = arc[1].y - arc[0].y; 1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov s = FT_ABS( dy * dx1 - dx * dy1 ); 1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( s > s_limit ) 1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Split; 1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* s is L * the perpendicular distance from P2 to the line P0-P3. */ 1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx2 = arc[2].x - arc[0].x; 1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dy2 = arc[2].y - arc[0].y; 1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov s = FT_ABS( dy * dx2 - dx * dy2 ); 1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( s > s_limit ) 1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Split; 1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Split super curvy segments where the off points are so far 1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov from the chord that the angles P0-P1-P3 or P0-P2-P3 become 1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov acute as detected by appropriate dot products. */ 1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || 1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) 1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Split; 1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* No reason to split. */ 1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Draw; 1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Split: 1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_split_cubic( arc ); 1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc += 3; 1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Draw: 1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); 1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( arc == ras.bez_stack ) 1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov arc -= 3; 1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_move_to( const FT_Vector* to, 1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker ) 1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos x, y; 1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* record current cell, if any */ 1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_record_cell( RAS_VAR ); 1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start to a new position */ 1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = UPSCALE( to->x ); 1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = UPSCALE( to->y ); 1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) ); 1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov worker->x = x; 1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov worker->y = y; 1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_line_to( const FT_Vector* to, 1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker ) 1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) ); 1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_conic_to( const FT_Vector* control, 1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* to, 1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker ) 1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_conic( RAS_VAR_ control, to ); 1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_cubic_to( const FT_Vector* control1, 1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* control2, 1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Vector* to, 1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker ) 1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_cubic( RAS_VAR_ control1, control2, to ); 1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_render_span( int y, 1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int count, 1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Span* spans, 1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker ) 1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char* p; 1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Bitmap* map = &worker->target; 1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first of all, compute the scanline offset */ 1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p = (unsigned char*)map->buffer - y * map->pitch; 1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( map->pitch >= 0 ) 1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov p += (unsigned)( ( map->rows - 1 ) * map->pitch ); 1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; count > 0; count--, spans++ ) 1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char coverage = spans->coverage; 1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coverage ) 1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* For small-spans it is faster to do it by ourselves than 1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * calling `memset'. This is mainly due to the cost of the 1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * function call. 1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( spans->len >= 8 ) 1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len ); 1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov unsigned char* q = p + spans->x; 1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( spans->len ) 1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 7: *q++ = (unsigned char)coverage; 1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 6: *q++ = (unsigned char)coverage; 1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 5: *q++ = (unsigned char)coverage; 1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 4: *q++ = (unsigned char)coverage; 1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 3: *q++ = (unsigned char)coverage; 1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 2: *q++ = (unsigned char)coverage; 1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case 1: *q = (unsigned char)coverage; 1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: 1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ; 1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_hline( RAS_ARG_ TCoord x, 1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord y, 1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos area, 1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord acount ) 1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int coverage; 1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute the coverage line's coverage, depending on the */ 1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* outline fill rule */ 1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */ 1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); 1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* use range 0..256 */ 1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coverage < 0 ) 1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage = -coverage; 1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) 1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage &= 511; 1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coverage > 256 ) 1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage = 512 - coverage; 1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( coverage == 256 ) 1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage = 255; 1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* normal non-zero winding rule */ 1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coverage >= 256 ) 1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov coverage = 255; 1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y += (TCoord)ras.min_ey; 1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x += (TCoord)ras.min_ex; 1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */ 1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( x >= 32767 ) 1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = 32767; 1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FT_Span.y is an integer, so limit our coordinates appropriately */ 1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( y >= FT_INT_MAX ) 1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov y = FT_INT_MAX; 1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( coverage ) 1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Span* span; 1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int count; 1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* see whether we can add this span to the current list */ 1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = ras.num_gray_spans; 1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span = ras.gray_spans + count - 1; 1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( count > 0 && 1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.span_y == y && 1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (int)span->x + span->len == (int)x && 1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->coverage == coverage ) 1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->len = (unsigned short)( span->len + acount ); 1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS ) 1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.render_span && count > 0 ) 1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span( ras.span_y, count, ras.gray_spans, 1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span_data ); 1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( count > 0 ) 1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; 1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "y = %3d ", ras.span_y )); 1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span = ras.gray_spans; 1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < count; n++, span++ ) 1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "[%d..%d]:%02x ", 1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->x, span->x + span->len - 1, span->coverage )); 1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "\n" )); 1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_DEBUG_LEVEL_TRACE */ 1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_gray_spans = 0; 1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.span_y = (int)y; 1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov count = 0; 1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span = ras.gray_spans; 1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span++; 1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Fix the Vulnerability Report FoxIT Reader - MSVR-10-0077. 1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Limited to the value range of 'x', we have to crop it for avoid the overflow. 1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if (x < 32768) { 1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* add a gray span to the current list */ 1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->x = (short)x; 1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->len = (unsigned short)acount; 1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->coverage = (unsigned char)coverage; 1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_gray_spans++; 1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* to be called while in the debugger -- */ 1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this function causes a compiler warning since it is unused otherwise */ 1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_dump_cells( RAS_ARG ) 1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int yindex; 1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( yindex = 0; yindex < ras.ycount; yindex++ ) 1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell cell; 1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov printf( "%3d:", yindex ); 1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next ) 1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area ); 1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov printf( "\n" ); 1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_DEBUG_LEVEL_TRACE */ 1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_sweep( RAS_ARG_ const FT_Bitmap* target ) 1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int yindex; 1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( target ); 1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.num_cells == 0 ) 1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return; 1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_gray_spans = 0; 1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "gray_sweep: start\n" )); 1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( yindex = 0; yindex < ras.ycount; yindex++ ) 1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell cell = ras.ycells[yindex]; 1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord cover = 0; 1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TCoord x = 0; 1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( ; cell != NULL; cell = cell->next ) 1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos area; 1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cell->x > x && cover != 0 ) 1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), 1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell->x - x ); 1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cover += cell->cover; 1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov area = cover * ( ONE_PIXEL * 2 ) - cell->area; 1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( area != 0 && cell->x >= 0 ) 1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_hline( RAS_VAR_ cell->x, yindex, area, 1 ); 1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov x = cell->x + 1; 1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cover != 0 ) 1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ), 1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.count_ex - x ); 1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.render_span && ras.num_gray_spans > 0 ) 1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span( ras.span_y, ras.num_gray_spans, 1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.gray_spans, ras.render_span_data ); 1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.num_gray_spans > 0 ) 1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Span* span; 1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; 1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "y = %3d ", ras.span_y )); 1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span = ras.gray_spans; 1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < ras.num_gray_spans; n++, span++ ) 1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "[%d..%d]:%02x ", 1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov span->x, span->x + span->len - 1, span->coverage )); 1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "\n" )); 1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "gray_sweep: end\n" )); 1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* FT_DEBUG_LEVEL_TRACE */ 1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _STANDALONE_ 1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* The following function should only compile in stand-alone mode, */ 1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* i.e., when building this component without the rest of FreeType. */ 1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /*************************************************************************/ 1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Function> */ 1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* FT_Outline_Decompose */ 1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Description> */ 1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Walk over an outline's structure to decompose it into individual */ 1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* segments and Bézier arcs. This function is also able to emit */ 1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* `move to' and `close to' operations to indicate the start and end */ 1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* of new contours in the outline. */ 1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Input> */ 1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* outline :: A pointer to the source target. */ 1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* func_interface :: A table of `emitters', i.e., function pointers */ 1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* called during decomposition to indicate path */ 1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* operations. */ 1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <InOut> */ 1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* user :: A typeless pointer which is passed to each */ 1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* emitter during the decomposition. It can be */ 1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* used to store the state during the */ 1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* decomposition. */ 1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* <Return> */ 1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Error code. 0 means success. */ 1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* */ 1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Decompose( const FT_Outline* outline, 1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Outline_Funcs* func_interface, 1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov void* user ) 1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#undef SCALED 1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define SCALED( x ) ( ( (x) << shift ) - delta ) 1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_last; 1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_control; 1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_start; 1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* point; 1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector* limit; 1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* tags; 1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int error; 1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int n; /* index of contour in outline */ 1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int first; /* index of first point in contour */ 1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char tag; /* current point's state */ 1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int shift; 1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos delta; 1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline || !func_interface ) 1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov shift = func_interface->shift; 1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov delta = func_interface->delta; 1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = 0; 1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < outline->n_contours; n++ ) 1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int last; /* index of last point in contour */ 1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n )); 1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov last = outline->contours[n]; 1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( last < 0 ) 1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit = outline->points + last; 1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start = outline->points[first]; 1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x = SCALED( v_start.x ); 1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.y = SCALED( v_start.y ); 1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last = outline->points[last]; 1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last.x = SCALED( v_last.x ); 1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last.y = SCALED( v_last.y ); 1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control = v_start; 1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point = outline->points + first; 1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags = outline->tags + first; 1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* A contour cannot start with a cubic control point! */ 1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_CUBIC ) 1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* check first point to determine origin */ 1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_CONIC ) 1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* first point is conic control. Yes, this happens. */ 1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) 1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start at last point if it is on the curve */ 1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start = v_last; 1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov limit--; 1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if both first and last points are conic, */ 1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* start at their middle and record its position */ 1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* for closure */ 1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x = ( v_start.x + v_last.x ) / 2; 1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.y = ( v_start.y + v_last.y ) / 2; 1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_last = v_start; 1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point--; 1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags--; 1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " move to (%.2f, %.2f)\n", 1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0 )); 1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->move_to( &v_start, user ); 1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( point < limit ) 1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point++; 1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags++; 1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov switch ( tag ) 1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case FT_CURVE_TAG_ON: /* emit a single line_to */ 1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " line to (%.2f, %.2f)\n", 1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0 )); 1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->line_to( &vec, user ); 1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov case FT_CURVE_TAG_CONIC: /* consume conic arcs */ 1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x = SCALED( point->x ); 1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.y = SCALED( point->y ); 1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Do_Conic: 1634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point < limit ) 1635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 1637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector v_middle; 1638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point++; 1641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags++; 1642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tag = FT_CURVE_TAG( tags[0] ); 1643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 1645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 1646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag == FT_CURVE_TAG_ON ) 1648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 1650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 1651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0, 1652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 1653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &vec, user ); 1654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( tag != FT_CURVE_TAG_CONIC ) 1660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 1661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.x = ( v_control.x + vec.x ) / 2; 1663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.y = ( v_control.y + vec.y ) / 2; 1664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 1666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 1667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_middle.x / 64.0, v_middle.y / 64.0, 1668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 1669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &v_middle, user ); 1670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control = vec; 1674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Do_Conic; 1675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " conic to (%.2f, %.2f)" 1678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with control (%.2f, %.2f)\n", 1679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0, 1680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_control.x / 64.0, v_control.y / 64.0 )); 1681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->conic_to( &v_control, &v_start, user ); 1682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Close; 1683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov default: /* FT_CURVE_TAG_CUBIC */ 1685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec1, vec2; 1687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point + 1 > limit || 1690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) 1691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Invalid_Outline; 1692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov point += 2; 1694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov tags += 2; 1695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x = SCALED( point[-2].x ); 1697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.y = SCALED( point[-2].y ); 1698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x = SCALED( point[-1].x ); 1700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.y = SCALED( point[-1].y ); 1701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( point <= limit ) 1703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Vector vec; 1705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x = SCALED( point->x ); 1708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.y = SCALED( point->y ); 1709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " cubic to (%.2f, %.2f)" 1711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 1712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec.x / 64.0, vec.y / 64.0, 1713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x / 64.0, vec1.y / 64.0, 1714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x / 64.0, vec2.y / 64.0 )); 1715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->cubic_to( &vec1, &vec2, &vec, user ); 1716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " cubic to (%.2f, %.2f)" 1722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov " with controls (%.2f, %.2f) and (%.2f, %.2f)\n", 1723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0, 1724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec1.x / 64.0, vec1.y / 64.0, 1725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov vec2.x / 64.0, vec2.y / 64.0 )); 1726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->cubic_to( &vec1, &vec2, &v_start, user ); 1727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Close; 1728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* close the contour with a line segment */ 1733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( " line to (%.2f, %.2f)\n", 1734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov v_start.x / 64.0, v_start.y / 64.0 )); 1735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = func_interface->line_to( &v_start, user ); 1736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Close: 1738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( error ) 1739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto Exit; 1740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov first = last + 1; 1742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Done\n", n )); 1745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Exit: 1748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error )); 1749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Invalid_Outline: 1752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Outline ); 1753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* _STANDALONE_ */ 1756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov typedef struct gray_TBand_ 1759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos min, max; 1761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } gray_TBand; 1763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_OUTLINE_FUNCS(func_interface, 1765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Outline_MoveTo_Func) gray_move_to, 1766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Outline_LineTo_Func) gray_line_to, 1767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Outline_ConicTo_Func)gray_conic_to, 1768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Outline_CubicTo_Func)gray_cubic_to, 1769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0, 1770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 0 1771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ) 1772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_convert_glyph_inner( RAS_ARG ) 1775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov volatile int error = 0; 1778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_CONFIG_OPTION_PIC 1780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Outline_Funcs func_interface; 1781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov Init_Class_func_interface(&func_interface); 1782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_MANAGED_CODE_ 1784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ft_setjmp( ras.jump_buffer ) == 0 ) 1785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras ); 1788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_record_cell( RAS_VAR ); 1789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifndef _FX_MANAGED_CODE_ 1790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = FT_THROW( Memory_Overflow ); 1793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 1795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_convert_glyph( RAS_ARG ) 1800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_TBand bands[40]; 1802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_TBand* volatile band; 1803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int volatile n, num_bands; 1804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos volatile min, max, max_y; 1805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_BBox* clip; 1806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* Set up state in the raster object */ 1809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_compute_cbox( RAS_VAR ); 1810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* clip to target bitmap, exit if nothing to do */ 1812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov clip = &ras.clip_box; 1813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax || 1815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax ) 1816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin; 1819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin; 1820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax; 1822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax; 1823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.count_ex = ras.max_ex - ras.min_ex; 1825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.count_ey = ras.max_ey - ras.min_ey; 1826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* set up vertical bands */ 1828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size ); 1829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_bands == 0 ) 1830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_bands = 1; 1831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( num_bands >= 39 ) 1832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov num_bands = 39; 1833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.band_shoot = 0; 1835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov min = ras.min_ey; 1837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max_y = ras.max_ey; 1838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( n = 0; n < num_bands; n++, min = max ) 1840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = min + ras.band_size; 1842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( n == num_bands - 1 || max > max_y ) 1843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov max = max_y; 1844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bands[0].min = min; 1846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bands[0].max = max; 1847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band = bands; 1848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov while ( band >= bands ) 1850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov TPos bottom, top, middle; 1852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int error; 1853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov PCell cells_max; 1856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov int yindex; 1857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long cell_start, cell_end, cell_mod; 1858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ycells = (PCell*)ras.buffer; 1861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ycount = band->max - band->min; 1862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell_start = sizeof ( PCell ) * ras.ycount; 1864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell_mod = cell_start % sizeof ( TCell ); 1865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( cell_mod > 0 ) 1866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell_start += sizeof ( TCell ) - cell_mod; 1867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell_end = ras.buffer_size; 1869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cell_end -= cell_end % sizeof ( TCell ); 1870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cells_max = (PCell)( (char*)ras.buffer + cell_end ); 1872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.cells = (PCell)( (char*)ras.buffer + cell_start ); 1873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.cells >= cells_max ) 1874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto ReduceBands; 1875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_cells = cells_max - ras.cells; 1877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.max_cells < 2 ) 1878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov goto ReduceBands; 1879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov for ( yindex = 0; yindex < ras.ycount; yindex++ ) 1881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.ycells[yindex] = NULL; 1882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_cells = 0; 1885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.invalid = 1; 1886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.min_ey = band->min; 1887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.max_ey = band->max; 1888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.count_ey = band->max - band->min; 1889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov error = gray_convert_glyph_inner( RAS_VAR ); 1891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !error ) 1893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_sweep( RAS_VAR_ &ras.target ); 1895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band--; 1896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov continue; 1897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( error != ErrRaster_Memory_Overflow ) 1899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 1900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ReduceBands: 1902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* render pool overflow; we will reduce the render band by half */ 1903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov bottom = band->min; 1904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov top = band->max; 1905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov middle = bottom + ( ( top - bottom ) >> 1 ); 1906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* This is too complex for a single scanline; there must */ 1908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* be some problems. */ 1909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( middle == bottom ) 1910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_DEBUG_LEVEL_TRACE 1912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" )); 1913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif 1914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 1; 1915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( bottom-top >= ras.band_size ) 1918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.band_shoot++; 1919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band[1].min = bottom; 1921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band[1].max = middle; 1922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band[0].min = middle; 1923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band[0].max = top; 1924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov band++; 1925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( ras.band_shoot > 8 && ras.band_size > 16 ) 1929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.band_size = ras.band_size / 2; 1930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 1936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_render( gray_PRaster raster, 1937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Raster_Params* params ) 1938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Outline* outline = (const FT_Outline*)params->source; 1940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov const FT_Bitmap* target_map = params->target; 1941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker; 1942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !raster || !raster->buffer || !raster->buffer_size ) 1945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 1946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline ) 1948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Outline ); 1949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* return immediately if the outline is empty */ 1951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_points == 0 || outline->n_contours <= 0 ) 1952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !outline->contours || !outline->points ) 1955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Outline ); 1956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( outline->n_points != 1958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov outline->contours[outline->n_contours - 1] + 1 ) 1959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Outline ); 1960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov worker = raster->worker; 1962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* if direct mode is not set, we must have a target bitmap */ 1964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) ) 1965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !target_map ) 1967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 1968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nothing to do */ 1970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !target_map->width || !target_map->rows ) 1971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 1972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !target_map->buffer ) 1974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Argument ); 1975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* this version does not support monochrome rendering */ 1978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( params->flags & FT_RASTER_FLAG_AA ) ) 1979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return FT_THROW( Invalid_Mode ); 1980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 1981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute clipping box */ 1982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) ) 1983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* compute clip box from target pixmap */ 1985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.xMin = 0; 1986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.yMin = 0; 1987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.xMax = target_map->width; 1988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.yMax = target_map->rows; 1989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else if ( params->flags & FT_RASTER_FLAG_CLIP ) 1991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box = params->clip_box; 1992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 1993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 1994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.xMin = -32768L; 1995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.yMin = -32768L; 1996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.xMax = 32767L; 1997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.clip_box.yMax = 32767L; 1998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 1999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size ); 2001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.outline = *outline; 2003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_cells = 0; 2004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.invalid = 1; 2005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.band_size = raster->band_size; 2006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.num_gray_spans = 0; 2007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( params->flags & FT_RASTER_FLAG_DIRECT ) 2009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span = (FT_Raster_Span_Func)params->gray_spans; 2011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span_data = params->user; 2012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.target = *target_map; 2016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span = (FT_Raster_Span_Func)gray_render_span; 2017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ras.render_span_data = &ras; 2018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return gray_convert_glyph( RAS_VAR ); 2021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/ 2025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /**** a static object. *****/ 2026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef _STANDALONE_ 2028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 2030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_new( void* memory, 2031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Raster* araster ) 2032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static gray_TRaster the_raster; 2034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( memory ); 2036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *araster = (FT_Raster)&the_raster; 2039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) ); 2040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return 0; 2042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 2046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_done( FT_Raster raster ) 2047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov /* nothing */ 2049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_UNUSED( raster ); 2050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !_STANDALONE_ */ 2053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static int 2055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_new( FT_Memory memory, 2056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Raster* araster ) 2057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Error error; 2059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PRaster raster = NULL; 2060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *araster = 0; 2063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) ) 2064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov raster->memory = memory; 2066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov *araster = (FT_Raster)raster; 2067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov return error; 2070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 2074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_done( FT_Raster raster ) 2075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_Memory memory = (FT_Memory)((gray_PRaster)raster)->memory; 2077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_FREE( raster ); 2080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !_STANDALONE_ */ 2083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov static void 2086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_raster_reset( FT_Raster raster, 2087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* pool_base, 2088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov long pool_size ) 2089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PRaster rast = (gray_PRaster)raster; 2091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( raster ) 2094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 ) 2096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov gray_PWorker worker = (gray_PWorker)pool_base; 2098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->worker = worker; 2101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->buffer = pool_base + 2102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( ( sizeof ( gray_TWorker ) + 2103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov sizeof ( TCell ) - 1 ) & 2104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ~( sizeof ( TCell ) - 1 ) ); 2105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->buffer_size = (long)( ( pool_base + pool_size ) - 2106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (char*)rast->buffer ) & 2107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ~( sizeof ( TCell ) - 1 ); 2108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->band_size = (int)( rast->buffer_size / 2109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ( sizeof ( TCell ) * 8 ) ); 2110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov else 2112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov { 2113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->buffer = NULL; 2114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->buffer_size = 0; 2115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov rast->worker = NULL; 2116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov } 2119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_DEFINE_RASTER_FUNCS(ft_grays_raster, 2122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov FT_GLYPH_FORMAT_OUTLINE, 2123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Raster_New_Func) gray_raster_new, 2125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Raster_Reset_Func) gray_raster_reset, 2126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Raster_Set_Mode_Func)0, 2127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Raster_Render_Func) gray_raster_render, 2128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov (FT_Raster_Done_Func) gray_raster_done 2129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov ) 2130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */ 2133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 2135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* Local Variables: */ 2136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* coding: utf-8 */ 2137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* End: */ 2138