PageRenderTime 188ms CodeModel.GetById 91ms app.highlight 84ms RepoModel.GetById 1ms app.codeStats 1ms

/src/freetype/src/raster/ftraster.c

https://bitbucket.org/cabalistic/ogredeps/
C | 3612 lines | 2079 code | 732 blank | 801 comment | 336 complexity | 7039c09154560704ab85e1459afc4098 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/***************************************************************************/
   2/*                                                                         */
   3/*  ftraster.c                                                             */
   4/*                                                                         */
   5/*    The FreeType glyph rasterizer (body).                                */
   6/*                                                                         */
   7/*  Copyright 1996-2003, 2005, 2007-2012 by                                */
   8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
   9/*                                                                         */
  10/*  This file is part of the FreeType project, and may only be used,       */
  11/*  modified, and distributed under the terms of the FreeType project      */
  12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13/*  this file you indicate that you have read the license and              */
  14/*  understand and accept it fully.                                        */
  15/*                                                                         */
  16/***************************************************************************/
  17
  18  /*************************************************************************/
  19  /*                                                                       */
  20  /* This file can be compiled without the rest of the FreeType engine, by */
  21  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
  22  /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
  23  /* directory.  Typically, you should do something like                   */
  24  /*                                                                       */
  25  /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
  26  /*                                                                       */
  27  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */
  28  /*   to your current directory                                           */
  29  /*                                                                       */
  30  /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
  31  /*                                                                       */
  32  /*     cc -c -D_STANDALONE_ ftraster.c                                   */
  33  /*                                                                       */
  34  /* The renderer can be initialized with a call to                        */
  35  /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
  36  /* with a call to `ft_standard_raster.raster_render'.                    */
  37  /*                                                                       */
  38  /* See the comments and documentation in the file `ftimage.h' for more   */
  39  /* details on how the raster works.                                      */
  40  /*                                                                       */
  41  /*************************************************************************/
  42
  43
  44  /*************************************************************************/
  45  /*                                                                       */
  46  /* This is a rewrite of the FreeType 1.x scan-line converter             */
  47  /*                                                                       */
  48  /*************************************************************************/
  49
  50#ifdef _STANDALONE_
  51
  52#define FT_CONFIG_STANDARD_LIBRARY_H  <stdlib.h>
  53
  54#include <string.h>           /* for memset */
  55
  56#include "ftmisc.h"
  57#include "ftimage.h"
  58
  59#else /* !_STANDALONE_ */
  60
  61#include <ft2build.h>
  62#include "ftraster.h"
  63#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
  64
  65#include "rastpic.h"
  66
  67#endif /* !_STANDALONE_ */
  68
  69
  70  /*************************************************************************/
  71  /*                                                                       */
  72  /* A simple technical note on how the raster works                       */
  73  /* -----------------------------------------------                       */
  74  /*                                                                       */
  75  /*   Converting an outline into a bitmap is achieved in several steps:   */
  76  /*                                                                       */
  77  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
  78  /*       profile is simply an array of scanline intersections on a given */
  79  /*       dimension.  A profile's main attributes are                     */
  80  /*                                                                       */
  81  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'      */
  82  /*                                                                       */
  83  /*       o an array of intersection coordinates for each scanline        */
  84  /*         between `Ymin' and `Ymax'                                     */
  85  /*                                                                       */
  86  /*       o a direction, indicating whether it was built going `up' or    */
  87  /*         `down', as this is very important for filling rules           */
  88  /*                                                                       */
  89  /*       o its drop-out mode                                             */
  90  /*                                                                       */
  91  /*   2 - Sweeping the target map's scanlines in order to compute segment */
  92  /*       `spans' which are then filled.  Additionally, this pass         */
  93  /*       performs drop-out control.                                      */
  94  /*                                                                       */
  95  /*   The outline data is parsed during step 1 only.  The profiles are    */
  96  /*   built from the bottom of the render pool, used as a stack.  The     */
  97  /*   following graphics shows the profile list under construction:       */
  98  /*                                                                       */
  99  /*     __________________________________________________________ _ _    */
 100  /*    |         |                 |         |                 |          */
 101  /*    | profile | coordinates for | profile | coordinates for |-->       */
 102  /*    |    1    |  profile 1      |    2    |  profile 2      |-->       */
 103  /*    |_________|_________________|_________|_________________|__ _ _    */
 104  /*                                                                       */
 105  /*    ^                                                       ^          */
 106  /*    |                                                       |          */
 107  /* start of render pool                                      top         */
 108  /*                                                                       */
 109  /*   The top of the profile stack is kept in the `top' variable.         */
 110  /*                                                                       */
 111  /*   As you can see, a profile record is pushed on top of the render     */
 112  /*   pool, which is then followed by its coordinates/intersections.  If  */
 113  /*   a change of direction is detected in the outline, a new profile is  */
 114  /*   generated until the end of the outline.                             */
 115  /*                                                                       */
 116  /*   Note that when all profiles have been generated, the function       */
 117  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
 118  /*   bottom-most scanline as well as the scanline above its upmost       */
 119  /*   boundary.  These positions are called `y-turns' because they (sort  */
 120  /*   of) correspond to local extrema.  They are stored in a sorted list  */
 121  /*   built from the top of the render pool as a downwards stack:         */
 122  /*                                                                       */
 123  /*      _ _ _______________________________________                      */
 124  /*                            |                    |                     */
 125  /*                         <--| sorted list of     |                     */
 126  /*                         <--|  extrema scanlines |                     */
 127  /*      _ _ __________________|____________________|                     */
 128  /*                                                                       */
 129  /*                            ^                    ^                     */
 130  /*                            |                    |                     */
 131  /*                         maxBuff           sizeBuff = end of pool      */
 132  /*                                                                       */
 133  /*   This list is later used during the sweep phase in order to          */
 134  /*   optimize performance (see technical note on the sweep below).       */
 135  /*                                                                       */
 136  /*   Of course, the raster detects whether the two stacks collide and    */
 137  /*   handles the situation properly.                                     */
 138  /*                                                                       */
 139  /*************************************************************************/
 140
 141
 142  /*************************************************************************/
 143  /*************************************************************************/
 144  /**                                                                     **/
 145  /**  CONFIGURATION MACROS                                               **/
 146  /**                                                                     **/
 147  /*************************************************************************/
 148  /*************************************************************************/
 149
 150  /* define DEBUG_RASTER if you want to compile a debugging version */
 151/* #define DEBUG_RASTER */
 152
 153  /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
 154  /* 5-levels anti-aliasing                                       */
 155/* #define FT_RASTER_OPTION_ANTI_ALIASING */
 156
 157  /* The size of the two-lines intermediate bitmap used */
 158  /* for anti-aliasing, in bytes.                       */
 159#define RASTER_GRAY_LINES  2048
 160
 161
 162  /*************************************************************************/
 163  /*************************************************************************/
 164  /**                                                                     **/
 165  /**  OTHER MACROS (do not change)                                       **/
 166  /**                                                                     **/
 167  /*************************************************************************/
 168  /*************************************************************************/
 169
 170  /*************************************************************************/
 171  /*                                                                       */
 172  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 173  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 174  /* messages during execution.                                            */
 175  /*                                                                       */
 176#undef  FT_COMPONENT
 177#define FT_COMPONENT  trace_raster
 178
 179
 180#ifdef _STANDALONE_
 181
 182
 183  /* This macro is used to indicate that a function parameter is unused. */
 184  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
 185  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
 186  /* ANSI compilers (e.g. LCC).                                          */
 187#define FT_UNUSED( x )  (x) = (x)
 188
 189  /* Disable the tracing mechanism for simplicity -- developers can      */
 190  /* activate it easily by redefining these two macros.                  */
 191#ifndef FT_ERROR
 192#define FT_ERROR( x )  do { } while ( 0 )     /* nothing */
 193#endif
 194
 195#ifndef FT_TRACE
 196#define FT_TRACE( x )   do { } while ( 0 )    /* nothing */
 197#define FT_TRACE1( x )  do { } while ( 0 )    /* nothing */
 198#define FT_TRACE6( x )  do { } while ( 0 )    /* nothing */
 199#endif
 200
 201#define Raster_Err_None          0
 202#define Raster_Err_Not_Ini      -1
 203#define Raster_Err_Overflow     -2
 204#define Raster_Err_Neg_Height   -3
 205#define Raster_Err_Invalid      -4
 206#define Raster_Err_Unsupported  -5
 207
 208#define ft_memset  memset
 209
 210#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
 211                                raster_reset_, raster_set_mode_,    \
 212                                raster_render_, raster_done_ )      \
 213          const FT_Raster_Funcs class_ =                            \
 214          {                                                         \
 215            glyph_format_,                                          \
 216            raster_new_,                                            \
 217            raster_reset_,                                          \
 218            raster_set_mode_,                                       \
 219            raster_render_,                                         \
 220            raster_done_                                            \
 221         };
 222
 223#else /* !_STANDALONE_ */
 224
 225
 226#include FT_INTERNAL_OBJECTS_H
 227#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
 228
 229#include "rasterrs.h"
 230
 231#define Raster_Err_None         Raster_Err_Ok
 232#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
 233#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
 234#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
 235#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
 236#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
 237
 238
 239#endif /* !_STANDALONE_ */
 240
 241
 242#ifndef FT_MEM_SET
 243#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
 244#endif
 245
 246#ifndef FT_MEM_ZERO
 247#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
 248#endif
 249
 250  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
 251  /* typically a small value and the result of a*b is known to fit into */
 252  /* 32 bits.                                                           */
 253#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
 254
 255  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
 256  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
 257  /* defined in `ftcalc.h'.                                                */
 258#define SMulDiv  FT_MulDiv
 259
 260  /* The rasterizer is a very general purpose component; please leave */
 261  /* the following redefinitions there (you never know your target    */
 262  /* environment).                                                    */
 263
 264#ifndef TRUE
 265#define TRUE   1
 266#endif
 267
 268#ifndef FALSE
 269#define FALSE  0
 270#endif
 271
 272#ifndef NULL
 273#define NULL  (void*)0
 274#endif
 275
 276#ifndef SUCCESS
 277#define SUCCESS  0
 278#endif
 279
 280#ifndef FAILURE
 281#define FAILURE  1
 282#endif
 283
 284
 285#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
 286                        /* Setting this constant to more than 32 is a   */
 287                        /* pure waste of space.                         */
 288
 289#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
 290
 291
 292  /*************************************************************************/
 293  /*************************************************************************/
 294  /**                                                                     **/
 295  /**  SIMPLE TYPE DECLARATIONS                                           **/
 296  /**                                                                     **/
 297  /*************************************************************************/
 298  /*************************************************************************/
 299
 300  typedef int             Int;
 301  typedef unsigned int    UInt;
 302  typedef short           Short;
 303  typedef unsigned short  UShort, *PUShort;
 304  typedef long            Long, *PLong;
 305
 306  typedef unsigned char   Byte, *PByte;
 307  typedef char            Bool;
 308
 309
 310  typedef union  Alignment_
 311  {
 312    long    l;
 313    void*   p;
 314    void  (*f)(void);
 315
 316  } Alignment, *PAlignment;
 317
 318
 319  typedef struct  TPoint_
 320  {
 321    Long  x;
 322    Long  y;
 323
 324  } TPoint;
 325
 326
 327  /* values for the `flags' bit field */
 328#define Flow_Up           0x8
 329#define Overshoot_Top     0x10
 330#define Overshoot_Bottom  0x20
 331
 332
 333  /* States of each line, arc, and profile */
 334  typedef enum  TStates_
 335  {
 336    Unknown_State,
 337    Ascending_State,
 338    Descending_State,
 339    Flat_State
 340
 341  } TStates;
 342
 343
 344  typedef struct TProfile_  TProfile;
 345  typedef TProfile*         PProfile;
 346
 347  struct  TProfile_
 348  {
 349    FT_F26Dot6  X;           /* current coordinate during sweep          */
 350    PProfile    link;        /* link to next profile (various purposes)  */
 351    PLong       offset;      /* start of profile's data in render pool   */
 352    unsigned    flags;       /* Bit 0-2: drop-out mode                   */
 353                             /* Bit 3: profile orientation (up/down)     */
 354                             /* Bit 4: is top profile?                   */
 355                             /* Bit 5: is bottom profile?                */
 356    long        height;      /* profile's height in scanlines            */
 357    long        start;       /* profile's starting scanline              */
 358
 359    unsigned    countL;      /* number of lines to step before this      */
 360                             /* profile becomes drawable                 */
 361
 362    PProfile    next;        /* next profile in same contour, used       */
 363                             /* during drop-out control                  */
 364  };
 365
 366  typedef PProfile   TProfileList;
 367  typedef PProfile*  PProfileList;
 368
 369
 370  /* Simple record used to implement a stack of bands, required */
 371  /* by the sub-banding mechanism                               */
 372  typedef struct  black_TBand_
 373  {
 374    Short  y_min;   /* band's minimum */
 375    Short  y_max;   /* band's maximum */
 376
 377  } black_TBand;
 378
 379
 380#define AlignProfileSize \
 381  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
 382
 383
 384#undef RAS_ARG
 385#undef RAS_ARGS
 386#undef RAS_VAR
 387#undef RAS_VARS
 388
 389#ifdef FT_STATIC_RASTER
 390
 391
 392#define RAS_ARGS       /* void */
 393#define RAS_ARG        /* void */
 394
 395#define RAS_VARS       /* void */
 396#define RAS_VAR        /* void */
 397
 398#define FT_UNUSED_RASTER  do { } while ( 0 )
 399
 400
 401#else /* !FT_STATIC_RASTER */
 402
 403
 404#define RAS_ARGS       black_PWorker  worker,
 405#define RAS_ARG        black_PWorker  worker
 406
 407#define RAS_VARS       worker,
 408#define RAS_VAR        worker
 409
 410#define FT_UNUSED_RASTER  FT_UNUSED( worker )
 411
 412
 413#endif /* !FT_STATIC_RASTER */
 414
 415
 416  typedef struct black_TWorker_  black_TWorker, *black_PWorker;
 417
 418
 419  /* prototypes used for sweep function dispatch */
 420  typedef void
 421  Function_Sweep_Init( RAS_ARGS Short*  min,
 422                                Short*  max );
 423
 424  typedef void
 425  Function_Sweep_Span( RAS_ARGS Short       y,
 426                                FT_F26Dot6  x1,
 427                                FT_F26Dot6  x2,
 428                                PProfile    left,
 429                                PProfile    right );
 430
 431  typedef void
 432  Function_Sweep_Step( RAS_ARG );
 433
 434
 435  /* NOTE: These operations are only valid on 2's complement processors */
 436#undef FLOOR
 437#undef CEILING
 438#undef TRUNC
 439#undef SCALED
 440
 441#define FLOOR( x )    ( (x) & -ras.precision )
 442#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
 443#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
 444#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
 445#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
 446
 447#define IS_BOTTOM_OVERSHOOT( x )  ( CEILING( x ) - x >= ras.precision_half )
 448#define IS_TOP_OVERSHOOT( x )     ( x - FLOOR( x ) >= ras.precision_half )
 449
 450  /* The most used variables are positioned at the top of the structure. */
 451  /* Thus, their offset can be coded with less opcodes, resulting in a   */
 452  /* smaller executable.                                                 */
 453
 454  struct  black_TWorker_
 455  {
 456    Int         precision_bits;     /* precision related variables         */
 457    Int         precision;
 458    Int         precision_half;
 459    Int         precision_shift;
 460    Int         precision_step;
 461    Int         precision_jitter;
 462
 463    Int         scale_shift;        /* == precision_shift   for bitmaps    */
 464                                    /* == precision_shift+1 for pixmaps    */
 465
 466    PLong       buff;               /* The profiles buffer                 */
 467    PLong       sizeBuff;           /* Render pool size                    */
 468    PLong       maxBuff;            /* Profiles buffer size                */
 469    PLong       top;                /* Current cursor in buffer            */
 470
 471    FT_Error    error;
 472
 473    Int         numTurns;           /* number of Y-turns in outline        */
 474
 475    TPoint*     arc;                /* current Bezier arc pointer          */
 476
 477    UShort      bWidth;             /* target bitmap width                 */
 478    PByte       bTarget;            /* target bitmap buffer                */
 479    PByte       gTarget;            /* target pixmap buffer                */
 480
 481    Long        lastX, lastY;
 482    Long        minY, maxY;
 483
 484    UShort      num_Profs;          /* current number of profiles          */
 485
 486    Bool        fresh;              /* signals a fresh new profile which   */
 487                                    /* `start' field must be completed     */
 488    Bool        joint;              /* signals that the last arc ended     */
 489                                    /* exactly on a scanline.  Allows      */
 490                                    /* removal of doublets                 */
 491    PProfile    cProfile;           /* current profile                     */
 492    PProfile    fProfile;           /* head of linked list of profiles     */
 493    PProfile    gProfile;           /* contour's first profile in case     */
 494                                    /* of impact                           */
 495
 496    TStates     state;              /* rendering state                     */
 497
 498    FT_Bitmap   target;             /* description of target bit/pixmap    */
 499    FT_Outline  outline;
 500
 501    Long        traceOfs;           /* current offset in target bitmap     */
 502    Long        traceG;             /* current offset in target pixmap     */
 503
 504    Short       traceIncr;          /* sweep's increment in target bitmap  */
 505
 506    Short       gray_min_x;         /* current min x during gray rendering */
 507    Short       gray_max_x;         /* current max x during gray rendering */
 508
 509    /* dispatch variables */
 510
 511    Function_Sweep_Init*  Proc_Sweep_Init;
 512    Function_Sweep_Span*  Proc_Sweep_Span;
 513    Function_Sweep_Span*  Proc_Sweep_Drop;
 514    Function_Sweep_Step*  Proc_Sweep_Step;
 515
 516    Byte        dropOutControl;     /* current drop_out control method     */
 517
 518    Bool        second_pass;        /* indicates whether a horizontal pass */
 519                                    /* should be performed to control      */
 520                                    /* drop-out accurately when calling    */
 521                                    /* Render_Glyph.  Note that there is   */
 522                                    /* no horizontal pass during gray      */
 523                                    /* rendering.                          */
 524
 525    TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
 526
 527    black_TBand  band_stack[16];    /* band stack used for sub-banding     */
 528    Int          band_top;          /* band stack top                      */
 529
 530#ifdef FT_RASTER_OPTION_ANTI_ALIASING
 531
 532    Byte*       grays;
 533
 534    Byte        gray_lines[RASTER_GRAY_LINES];
 535                                /* Intermediate table used to render the   */
 536                                /* graylevels pixmaps.                     */
 537                                /* gray_lines is a buffer holding two      */
 538                                /* monochrome scanlines                    */
 539
 540    Short       gray_width;     /* width in bytes of one monochrome        */
 541                                /* intermediate scanline of gray_lines.    */
 542                                /* Each gray pixel takes 2 bits long there */
 543
 544                       /* The gray_lines must hold 2 lines, thus with size */
 545                       /* in bytes of at least `gray_width*2'.             */
 546
 547#endif /* FT_RASTER_ANTI_ALIASING */
 548
 549  };
 550
 551
 552  typedef struct  black_TRaster_
 553  {
 554    char*          buffer;
 555    long           buffer_size;
 556    void*          memory;
 557    black_PWorker  worker;
 558    Byte           grays[5];
 559    Short          gray_width;
 560
 561  } black_TRaster, *black_PRaster;
 562
 563#ifdef FT_STATIC_RASTER
 564
 565  static black_TWorker  cur_ras;
 566#define ras  cur_ras
 567
 568#else /* !FT_STATIC_RASTER */
 569
 570#define ras  (*worker)
 571
 572#endif /* !FT_STATIC_RASTER */
 573
 574
 575#ifdef FT_RASTER_OPTION_ANTI_ALIASING
 576
 577  /* A lookup table used to quickly count set bits in four gray 2x2 */
 578  /* cells.  The values of the table have been produced with the    */
 579  /* following code:                                                */
 580  /*                                                                */
 581  /*   for ( i = 0; i < 256; i++ )                                  */
 582  /*   {                                                            */
 583  /*     l = 0;                                                     */
 584  /*     j = i;                                                     */
 585  /*                                                                */
 586  /*     for ( c = 0; c < 4; c++ )                                  */
 587  /*     {                                                          */
 588  /*       l <<= 4;                                                 */
 589  /*                                                                */
 590  /*       if ( j & 0x80 ) l++;                                     */
 591  /*       if ( j & 0x40 ) l++;                                     */
 592  /*                                                                */
 593  /*       j = ( j << 2 ) & 0xFF;                                   */
 594  /*     }                                                          */
 595  /*     printf( "0x%04X", l );                                     */
 596  /*   }                                                            */
 597  /*                                                                */
 598
 599  static const short  count_table[256] =
 600  {
 601    0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
 602    0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
 603    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
 604    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
 605    0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
 606    0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
 607    0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
 608    0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
 609    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
 610    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
 611    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
 612    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
 613    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
 614    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
 615    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
 616    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
 617    0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
 618    0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
 619    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
 620    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
 621    0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
 622    0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
 623    0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
 624    0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
 625    0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
 626    0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
 627    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
 628    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
 629    0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
 630    0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
 631    0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
 632    0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
 633  };
 634
 635#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
 636
 637
 638
 639  /*************************************************************************/
 640  /*************************************************************************/
 641  /**                                                                     **/
 642  /**  PROFILES COMPUTATION                                               **/
 643  /**                                                                     **/
 644  /*************************************************************************/
 645  /*************************************************************************/
 646
 647
 648  /*************************************************************************/
 649  /*                                                                       */
 650  /* <Function>                                                            */
 651  /*    Set_High_Precision                                                 */
 652  /*                                                                       */
 653  /* <Description>                                                         */
 654  /*    Set precision variables according to param flag.                   */
 655  /*                                                                       */
 656  /* <Input>                                                               */
 657  /*    High :: Set to True for high precision (typically for ppem < 18),  */
 658  /*            false otherwise.                                           */
 659  /*                                                                       */
 660  static void
 661  Set_High_Precision( RAS_ARGS Int  High )
 662  {
 663    /*
 664     * `precision_step' is used in `Bezier_Up' to decide when to split a
 665     * given y-monotonous Bezier arc that crosses a scanline before
 666     * approximating it as a straight segment.  The default value of 32 (for
 667     * low accuracy) corresponds to
 668     *
 669     *   32 / 64 == 0.5 pixels ,
 670     *
 671     * while for the high accuracy case we have
 672     *
 673     *   256/ (1 << 12) = 0.0625 pixels .
 674     *
 675     * `precision_jitter' is an epsilon threshold used in
 676     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
 677     * decomposition (after all, we are working with approximations only);
 678     * it avoids switching on additional pixels which would cause artifacts
 679     * otherwise.
 680     *
 681     * The value of `precision_jitter' has been determined heuristically.
 682     *
 683     */
 684
 685    if ( High )
 686    {
 687      ras.precision_bits   = 12;
 688      ras.precision_step   = 256;
 689      ras.precision_jitter = 30;
 690    }
 691    else
 692    {
 693      ras.precision_bits   = 6;
 694      ras.precision_step   = 32;
 695      ras.precision_jitter = 2;
 696    }
 697
 698    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
 699
 700    ras.precision       = 1 << ras.precision_bits;
 701    ras.precision_half  = ras.precision / 2;
 702    ras.precision_shift = ras.precision_bits - Pixel_Bits;
 703  }
 704
 705
 706  /*************************************************************************/
 707  /*                                                                       */
 708  /* <Function>                                                            */
 709  /*    New_Profile                                                        */
 710  /*                                                                       */
 711  /* <Description>                                                         */
 712  /*    Create a new profile in the render pool.                           */
 713  /*                                                                       */
 714  /* <Input>                                                               */
 715  /*    aState    :: The state/orientation of the new profile.             */
 716  /*                                                                       */
 717  /*    overshoot :: Whether the profile's unrounded start position        */
 718  /*                 differs by at least a half pixel.                     */
 719  /*                                                                       */
 720  /* <Return>                                                              */
 721  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
 722  /*   profile.                                                            */
 723  /*                                                                       */
 724  static Bool
 725  New_Profile( RAS_ARGS TStates  aState,
 726                        Bool     overshoot )
 727  {
 728    if ( !ras.fProfile )
 729    {
 730      ras.cProfile  = (PProfile)ras.top;
 731      ras.fProfile  = ras.cProfile;
 732      ras.top      += AlignProfileSize;
 733    }
 734
 735    if ( ras.top >= ras.maxBuff )
 736    {
 737      ras.error = Raster_Err_Overflow;
 738      return FAILURE;
 739    }
 740
 741    ras.cProfile->flags  = 0;
 742    ras.cProfile->start  = 0;
 743    ras.cProfile->height = 0;
 744    ras.cProfile->offset = ras.top;
 745    ras.cProfile->link   = (PProfile)0;
 746    ras.cProfile->next   = (PProfile)0;
 747    ras.cProfile->flags  = ras.dropOutControl;
 748
 749    switch ( aState )
 750    {
 751    case Ascending_State:
 752      ras.cProfile->flags |= Flow_Up;
 753      if ( overshoot )
 754        ras.cProfile->flags |= Overshoot_Bottom;
 755
 756      FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));
 757      break;
 758
 759    case Descending_State:
 760      if ( overshoot )
 761        ras.cProfile->flags |= Overshoot_Top;
 762      FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
 763      break;
 764
 765    default:
 766      FT_ERROR(( "New_Profile: invalid profile direction\n" ));
 767      ras.error = Raster_Err_Invalid;
 768      return FAILURE;
 769    }
 770
 771    if ( !ras.gProfile )
 772      ras.gProfile = ras.cProfile;
 773
 774    ras.state = aState;
 775    ras.fresh = TRUE;
 776    ras.joint = FALSE;
 777
 778    return SUCCESS;
 779  }
 780
 781
 782  /*************************************************************************/
 783  /*                                                                       */
 784  /* <Function>                                                            */
 785  /*    End_Profile                                                        */
 786  /*                                                                       */
 787  /* <Description>                                                         */
 788  /*    Finalize the current profile.                                      */
 789  /*                                                                       */
 790  /* <Input>                                                               */
 791  /*    overshoot :: Whether the profile's unrounded end position differs  */
 792  /*                 by at least a half pixel.                             */
 793  /*                                                                       */
 794  /* <Return>                                                              */
 795  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
 796  /*                                                                       */
 797  static Bool
 798  End_Profile( RAS_ARGS Bool  overshoot )
 799  {
 800    Long      h;
 801    PProfile  oldProfile;
 802
 803
 804    h = (Long)( ras.top - ras.cProfile->offset );
 805
 806    if ( h < 0 )
 807    {
 808      FT_ERROR(( "End_Profile: negative height encountered\n" ));
 809      ras.error = Raster_Err_Neg_Height;
 810      return FAILURE;
 811    }
 812
 813    if ( h > 0 )
 814    {
 815      FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
 816                  ras.cProfile, ras.cProfile->start, h ));
 817
 818      ras.cProfile->height = h;
 819      if ( overshoot )
 820      {
 821        if ( ras.cProfile->flags & Flow_Up )
 822          ras.cProfile->flags |= Overshoot_Top;
 823        else
 824          ras.cProfile->flags |= Overshoot_Bottom;
 825      }
 826
 827      oldProfile   = ras.cProfile;
 828      ras.cProfile = (PProfile)ras.top;
 829
 830      ras.top += AlignProfileSize;
 831
 832      ras.cProfile->height = 0;
 833      ras.cProfile->offset = ras.top;
 834
 835      oldProfile->next = ras.cProfile;
 836      ras.num_Profs++;
 837    }
 838
 839    if ( ras.top >= ras.maxBuff )
 840    {
 841      FT_TRACE1(( "overflow in End_Profile\n" ));
 842      ras.error = Raster_Err_Overflow;
 843      return FAILURE;
 844    }
 845
 846    ras.joint = FALSE;
 847
 848    return SUCCESS;
 849  }
 850
 851
 852  /*************************************************************************/
 853  /*                                                                       */
 854  /* <Function>                                                            */
 855  /*    Insert_Y_Turn                                                      */
 856  /*                                                                       */
 857  /* <Description>                                                         */
 858  /*    Insert a salient into the sorted list placed on top of the render  */
 859  /*    pool.                                                              */
 860  /*                                                                       */
 861  /* <Input>                                                               */
 862  /*    New y scanline position.                                           */
 863  /*                                                                       */
 864  /* <Return>                                                              */
 865  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
 866  /*                                                                       */
 867  static Bool
 868  Insert_Y_Turn( RAS_ARGS Int  y )
 869  {
 870    PLong  y_turns;
 871    Int    y2, n;
 872
 873
 874    n       = ras.numTurns - 1;
 875    y_turns = ras.sizeBuff - ras.numTurns;
 876
 877    /* look for first y value that is <= */
 878    while ( n >= 0 && y < y_turns[n] )
 879      n--;
 880
 881    /* if it is <, simply insert it, ignore if == */
 882    if ( n >= 0 && y > y_turns[n] )
 883      while ( n >= 0 )
 884      {
 885        y2 = (Int)y_turns[n];
 886        y_turns[n] = y;
 887        y = y2;
 888        n--;
 889      }
 890
 891    if ( n < 0 )
 892    {
 893      ras.maxBuff--;
 894      if ( ras.maxBuff <= ras.top )
 895      {
 896        ras.error = Raster_Err_Overflow;
 897        return FAILURE;
 898      }
 899      ras.numTurns++;
 900      ras.sizeBuff[-ras.numTurns] = y;
 901    }
 902
 903    return SUCCESS;
 904  }
 905
 906
 907  /*************************************************************************/
 908  /*                                                                       */
 909  /* <Function>                                                            */
 910  /*    Finalize_Profile_Table                                             */
 911  /*                                                                       */
 912  /* <Description>                                                         */
 913  /*    Adjust all links in the profiles list.                             */
 914  /*                                                                       */
 915  /* <Return>                                                              */
 916  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
 917  /*                                                                       */
 918  static Bool
 919  Finalize_Profile_Table( RAS_ARG )
 920  {
 921    Int       bottom, top;
 922    UShort    n;
 923    PProfile  p;
 924
 925
 926    n = ras.num_Profs;
 927    p = ras.fProfile;
 928
 929    if ( n > 1 && p )
 930    {
 931      while ( n > 0 )
 932      {
 933        if ( n > 1 )
 934          p->link = (PProfile)( p->offset + p->height );
 935        else
 936          p->link = NULL;
 937
 938        if ( p->flags & Flow_Up )
 939        {
 940          bottom = (Int)p->start;
 941          top    = (Int)( p->start + p->height - 1 );
 942        }
 943        else
 944        {
 945          bottom     = (Int)( p->start - p->height + 1 );
 946          top        = (Int)p->start;
 947          p->start   = bottom;
 948          p->offset += p->height - 1;
 949        }
 950
 951        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
 952             Insert_Y_Turn( RAS_VARS top + 1 ) )
 953          return FAILURE;
 954
 955        p = p->link;
 956        n--;
 957      }
 958    }
 959    else
 960      ras.fProfile = NULL;
 961
 962    return SUCCESS;
 963  }
 964
 965
 966  /*************************************************************************/
 967  /*                                                                       */
 968  /* <Function>                                                            */
 969  /*    Split_Conic                                                        */
 970  /*                                                                       */
 971  /* <Description>                                                         */
 972  /*    Subdivide one conic Bezier into two joint sub-arcs in the Bezier   */
 973  /*    stack.                                                             */
 974  /*                                                                       */
 975  /* <Input>                                                               */
 976  /*    None (subdivided Bezier is taken from the top of the stack).       */
 977  /*                                                                       */
 978  /* <Note>                                                                */
 979  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
 980  /*    loop that should be optimized to hell to get the best performance. */
 981  /*                                                                       */
 982  static void
 983  Split_Conic( TPoint*  base )
 984  {
 985    Long  a, b;
 986
 987
 988    base[4].x = base[2].x;
 989    b = base[1].x;
 990    a = base[3].x = ( base[2].x + b ) / 2;
 991    b = base[1].x = ( base[0].x + b ) / 2;
 992    base[2].x = ( a + b ) / 2;
 993
 994    base[4].y = base[2].y;
 995    b = base[1].y;
 996    a = base[3].y = ( base[2].y + b ) / 2;
 997    b = base[1].y = ( base[0].y + b ) / 2;
 998    base[2].y = ( a + b ) / 2;
 999
1000    /* hand optimized.  gcc doesn't seem to be too good at common      */
1001    /* expression substitution and instruction scheduling ;-)          */
1002  }
1003
1004
1005  /*************************************************************************/
1006  /*                                                                       */
1007  /* <Function>                                                            */
1008  /*    Split_Cubic                                                        */
1009  /*                                                                       */
1010  /* <Description>                                                         */
1011  /*    Subdivide a third-order Bezier arc into two joint sub-arcs in the  */
1012  /*    Bezier stack.                                                      */
1013  /*                                                                       */
1014  /* <Note>                                                                */
1015  /*    This routine is the `beef' of the component.  It is one of _the_   */
1016  /*    inner loops that should be optimized like hell to get the best     */
1017  /*    performance.                                                       */
1018  /*                                                                       */
1019  static void
1020  Split_Cubic( TPoint*  base )
1021  {
1022    Long  a, b, c, d;
1023
1024
1025    base[6].x = base[3].x;
1026    c = base[1].x;
1027    d = base[2].x;
1028    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
1029    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
1030    c = ( c + d + 1 ) >> 1;
1031    base[2].x = a = ( a + c + 1 ) >> 1;
1032    base[4].x = b = ( b + c + 1 ) >> 1;
1033    base[3].x = ( a + b + 1 ) >> 1;
1034
1035    base[6].y = base[3].y;
1036    c = base[1].y;
1037    d = base[2].y;
1038    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
1039    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
1040    c = ( c + d + 1 ) >> 1;
1041    base[2].y = a = ( a + c + 1 ) >> 1;
1042    base[4].y = b = ( b + c + 1 ) >> 1;
1043    base[3].y = ( a + b + 1 ) >> 1;
1044  }
1045
1046
1047  /*************************************************************************/
1048  /*                                                                       */
1049  /* <Function>                                                            */
1050  /*    Line_Up                                                            */
1051  /*                                                                       */
1052  /* <Description>                                                         */
1053  /*    Compute the x-coordinates of an ascending line segment and store   */
1054  /*    them in the render pool.                                           */
1055  /*                                                                       */
1056  /* <Input>                                                               */
1057  /*    x1   :: The x-coordinate of the segment's start point.             */
1058  /*                                                                       */
1059  /*    y1   :: The y-coordinate of the segment's start point.             */
1060  /*                                                                       */
1061  /*    x2   :: The x-coordinate of the segment's end point.               */
1062  /*                                                                       */
1063  /*    y2   :: The y-coordinate of the segment's end point.               */
1064  /*                                                                       */
1065  /*    miny :: A lower vertical clipping bound value.                     */
1066  /*                                                                       */
1067  /*    maxy :: An upper vertical clipping bound value.                    */
1068  /*                                                                       */
1069  /* <Return>                                                              */
1070  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1071  /*                                                                       */
1072  static Bool
1073  Line_Up( RAS_ARGS Long  x1,
1074                    Long  y1,
1075                    Long  x2,
1076                    Long  y2,
1077                    Long  miny,
1078                    Long  maxy )
1079  {
1080    Long   Dx, Dy;
1081    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
1082    Long   Ix, Rx, Ax;
1083
1084    PLong  top;
1085
1086
1087    Dx = x2 - x1;
1088    Dy = y2 - y1;
1089
1090    if ( Dy <= 0 || y2 < miny || y1 > maxy )
1091      return SUCCESS;
1092
1093    if ( y1 < miny )
1094    {
1095      /* Take care: miny-y1 can be a very large value; we use     */
1096      /*            a slow MulDiv function to avoid clipping bugs */
1097      x1 += SMulDiv( Dx, miny - y1, Dy );
1098      e1  = (Int)TRUNC( miny );
1099      f1  = 0;
1100    }
1101    else
1102    {
1103      e1 = (Int)TRUNC( y1 );
1104      f1 = (Int)FRAC( y1 );
1105    }
1106
1107    if ( y2 > maxy )
1108    {
1109      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
1110      e2  = (Int)TRUNC( maxy );
1111      f2  = 0;
1112    }
1113    else
1114    {
1115      e2 = (Int)TRUNC( y2 );
1116      f2 = (Int)FRAC( y2 );
1117    }
1118
1119    if ( f1 > 0 )
1120    {
1121      if ( e1 == e2 )
1122        return SUCCESS;
1123      else
1124      {
1125        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
1126        e1 += 1;
1127      }
1128    }
1129    else
1130      if ( ras.joint )
1131      {
1132        ras.top--;
1133        ras.joint = FALSE;
1134      }
1135
1136    ras.joint = (char)( f2 == 0 );
1137
1138    if ( ras.fresh )
1139    {
1140      ras.cProfile->start = e1;
1141      ras.fresh           = FALSE;
1142    }
1143
1144    size = e2 - e1 + 1;
1145    if ( ras.top + size >= ras.maxBuff )
1146    {
1147      ras.error = Raster_Err_Overflow;
1148      return FAILURE;
1149    }
1150
1151    if ( Dx > 0 )
1152    {
1153      Ix = SMulDiv( ras.precision, Dx, Dy);
1154      Rx = ( ras.precision * Dx ) % Dy;
1155      Dx = 1;
1156    }
1157    else
1158    {
1159      Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
1160      Rx =    ( ras.precision * -Dx ) % Dy;
1161      Dx = -1;
1162    }
1163
1164    Ax  = -Dy;
1165    top = ras.top;
1166
1167    while ( size > 0 )
1168    {
1169      *top++ = x1;
1170
1171      x1 += Ix;
1172      Ax += Rx;
1173      if ( Ax >= 0 )
1174      {
1175        Ax -= Dy;
1176        x1 += Dx;
1177      }
1178      size--;
1179    }
1180
1181    ras.top = top;
1182    return SUCCESS;
1183  }
1184
1185
1186  /*************************************************************************/
1187  /*                                                                       */
1188  /* <Function>                                                            */
1189  /*    Line_Down                                                          */
1190  /*                                                                       */
1191  /* <Description>                                                         */
1192  /*    Compute the x-coordinates of an descending line segment and store  */
1193  /*    them in the render pool.                                           */
1194  /*                                                                       */
1195  /* <Input>                                                               */
1196  /*    x1   :: The x-coordinate of the segment's start point.             */
1197  /*                                                                       */
1198  /*    y1   :: The y-coordinate of the segment's start point.             */
1199  /*                                                                       */
1200  /*    x2   :: The x-coordinate of the segment's end point.               */
1201  /*                                                                       */
1202  /*    y2   :: The y-coordinate of the segment's end point.               */
1203  /*                                                                       */
1204  /*    miny :: A lower vertical clipping bound value.                     */
1205  /*                                                                       */
1206  /*    maxy :: An upper vertical clipping bound value.                    */
1207  /*                                                                       */
1208  /* <Return>                                                              */
1209  /*    SUCCESS on success, FAILURE on render pool overflow.               */
1210  /*                                                                       */
1211  static Bool
1212  Line_Down( RAS_ARGS Long  x1,
1213                      Long  y1,
1214                      Long  x2,
1215                      Long  y2,
1216                      Long  miny,
1217                      Long  maxy )
1218  {
1219    Bool  result, fresh;
1220
1221
1222    fresh  = ras.fresh;
1223
1224    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny 

Large files files are truncated, but you can click here to view the full file