⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftgrays.c

📁 qt-embedded-2.3.8.tar.gz源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************//*                                                                         *//*  ftgrays.c                                                              *//*                                                                         *//*    A new `perfect' anti-aliasing renderer (body).                       *//*                                                                         *//*  Copyright 2000 by                                                      *//*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *//*                                                                         *//*  This file is part of the FreeType project, and may only be used,       *//*  modified, and distributed under the terms of the FreeType project      *//*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//***************************************************************************/  /*************************************************************************/  /*                                                                       */  /*  This file can be compiled without the rest of the FreeType engine,   */  /*  by defining the _STANDALONE_ macro when compiling it.  You also need */  /*  to put the files `ftgrays.h' and `ftimage.h' into the current        */  /*  compilation directory.  Typically, you could do something like       */  /*                                                                       */  /*  - copy `src/base/ftgrays.c' to your current directory                */  /*                                                                       */  /*  - copy `include/freetype/ftimage.h' and                              */  /*    `include/freetype/ftgrays.h' to the same directory                 */  /*                                                                       */  /*  - compile `ftgrays' with the _STANDALONE_ macro defined, as in       */  /*                                                                       */  /*      cc -c -D_STANDALONE_ ftgrays.c                                   */  /*                                                                       */  /*  The renderer can be initialized with a call to                       */  /*  `ft_grays_raster.grays_raster_new'; an anti-aliased bitmap can be    */  /*  generated with a call to `ft_grays_raster.grays_raster_render'.      */  /*                                                                       */  /*  See the comments and documentation in the file `ftimage.h' for       */  /*  more details on how the raster works.                                */  /*                                                                       */  /*************************************************************************/  /*************************************************************************/  /*                                                                       */  /*  This is a new anti-aliasing scan-converter for FreeType 2.  The      */  /*  algorithm used here is _very_ different from the one in the standard */  /*  `ftraster' module.  Actually, `ftgrays' computes the _exact_         */  /*  coverage of the outline on each pixel cell.                          */  /*                                                                       */  /*  It is based on ideas that I initially found in Raph Levien's         */  /*  excellent LibArt graphics library (see http://www.levien.com/libart  */  /*  for more information, though the web pages do not tell anything      */  /*  about the renderer; you'll have to dive into the source code to      */  /*  understand how it works).                                            */  /*                                                                       */  /*  Note, however, that this is a _very_ different implementation        */  /*  compared to Raph's.  Coverage information is stored in a very        */  /*  different way, and I don't use sorted vector paths.  Also, it        */  /*  doesn't use floating point values.                                   */  /*                                                                       */  /*  This renderer has the following advantages:                          */  /*                                                                       */  /*  - It doesn't need an intermediate bitmap.  Instead, one can supply   */  /*    a callback function that will be called by the renderer to draw    */  /*    gray spans on any target surface.  You can thus do direct          */  /*    composition on any kind of bitmap, provided that you give the      */  /*    renderer the right callback.                                       */  /*                                                                       */  /*  - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on  */  /*    each pixel cell                                                    */  /*                                                                       */  /*  - It performs a single pass on the outline (the `standard' FT2       */  /*    renderer makes two passes).                                        */  /*                                                                       */  /*  - It can easily be modified to render to _any_ number of gray levels */  /*    cheaply.                                                           */  /*                                                                       */  /*  - For small (< 20) pixel sizes, it is faster than the standard       */  /*    renderer.                                                          */  /*                                                                       */  /*************************************************************************/#include <string.h>             /* for memcpy() */  /*************************************************************************/  /*                                                                       */  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */  /* messages during execution.                                            */  /*                                                                       */#undef  FT_COMPONENT#define FT_COMPONENT  trace_aaraster#ifdef _STANDALONE_#define ErrRaster_Invalid_Mode     -2#define ErrRaster_Invalid_Outline  -1#include "ftimage.h"#include "ftgrays.h"  /* This macro is used to indicate that a function parameter is unused. */  /* Its purpose is simply to reduce compiler warnings.  Note also that  */  /* simply defining it as `(void)x' doesn't avoid warnings with certain */  /* ANSI compilers (e.g. LCC).                                          */#define FT_UNUSED( x )  (x) = (x)  /* Disable the tracing mechanism for simplicity -- developers can      */  /* activate it easily by redefining these two macros.                  */#ifndef FT_ERROR#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */#endif#ifndef FT_TRACE#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */#endif#else /* _STANDALONE_ */#ifdef FT_FLAT_COMPILE#include "ftgrays.h"#else#include <smooth/ftgrays.h>#endif#include <freetype/internal/ftobjs.h>  /* for FT_UNUSED()               */#include <freetype/internal/ftdebug.h> /* for FT_TRACE() and FT_ERROR() */#include <freetype/ftoutln.h>          /* for FT_Outline_Decompose()    */#define ErrRaster_Invalid_Mode     FT_Err_Cannot_Render_Glyph#define ErrRaster_Invalid_Outline  FT_Err_Invalid_Outline#endif /* _STANDALONE_ */  /* define this to dump debugging information */#define xxxDEBUG_GRAYS  /* as usual, for the speed hungry :-) */#ifndef FT_STATIC_RASTER#define RAS_ARG   PRaster  raster#define RAS_ARG_  PRaster  raster,#define RAS_VAR   raster#define RAS_VAR_  raster,#define ras       (*raster)#else /* FT_STATIC_RASTER */#define RAS_ARG   /* empty */#define RAS_ARG_  /* empty */#define RAS_VAR   /* empty */#define RAS_VAR_  /* empty */  static TRaster  ras;#endif /* FT_STATIC_RASTER */  /* must be at least 6 bits! */#define PIXEL_BITS  8#define ONE_PIXEL       ( 1L << PIXEL_BITS )#define PIXEL_MASK      ( -1L << PIXEL_BITS )#define TRUNC( x )      ( (x) >> PIXEL_BITS )#define SUBPIXELS( x )  ( (x) << PIXEL_BITS )#define FLOOR( x )      ( (x) & -ONE_PIXEL )#define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )#define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )#if PIXEL_BITS >= 6#define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )#define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )#else#define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )#define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )#endif  /* Define this if you want to use a more compact storage scheme.  This   */  /* increases the number of cells available in the render pool but slows  */  /* down the rendering a bit.  It is useful if you have a really tiny     */  /* render pool.                                                          */#define xxxGRAYS_COMPACT  /*************************************************************************/  /*                                                                       */  /*   TYPE DEFINITIONS                                                    */  /*                                                                       */  typedef int   TScan;   /* integer scanline/pixel coordinate */  typedef long  TPos;    /* sub-pixel coordinate              */  /* maximal number of gray spans in a call to the span callback */#define FT_MAX_GRAY_SPANS  32#ifdef GRAYS_COMPACT  typedef struct  TCell_  {    short  x     : 14;    short  y     : 14;    int    cover : PIXEL_BITS + 2;    int    area  : PIXEL_BITS * 2 + 2;  } TCell, *PCell;#else /* GRAYS_COMPACT */  typedef struct  TCell_  {    TScan  x;    TScan  y;    int    cover;    int    area;  } TCell, *PCell;#endif /* GRAYS_COMPACT */  typedef struct  TRaster_  {    PCell  cells;    int    max_cells;    int    num_cells;    TScan  min_ex, max_ex;    TScan  min_ey, max_ey;    int    area;    int    cover;    int    invalid;    TScan  ex, ey;    TScan  cx, cy;    TPos   x,  y;    TScan  last_ey;    FT_Vector   bez_stack[32 * 3];    int         lev_stack[32];    FT_Outline  outline;    FT_Bitmap   target;    FT_Span     gray_spans[FT_MAX_GRAY_SPANS];    int         num_gray_spans;    FT_Raster_Span_Func  render_span;    void*                render_span_data;    int                  span_y;    int    band_size;    int    band_shoot;    int    conic_level;    int    cubic_level;    void*  memory;  } TRaster, *PRaster;  /*************************************************************************/  /*                                                                       */  /* Initialize the cells table.                                           */  /*                                                                       */  static  void  init_cells( RAS_ARG_ void*  buffer,                    long            byte_size )  {    ras.cells     = (PCell)buffer;    ras.max_cells = byte_size / sizeof ( TCell );    ras.num_cells = 0;    ras.area      = 0;    ras.cover     = 0;    ras.invalid   = 1;  }  /*************************************************************************/  /*                                                                       */  /* Compute the outline bounding box.                                     */  /*                                                                       */  static  void  compute_cbox( RAS_ARG_ FT_Outline*  outline )  {    FT_Vector*  vec   = outline->points;    FT_Vector*  limit = vec + outline->n_points;    if ( outline->n_points <= 0 )    {      ras.min_ex = ras.max_ex = 0;      ras.min_ey = ras.max_ey = 0;      return;    }    ras.min_ex = ras.max_ex = vec->x;    ras.min_ey = ras.max_ey = vec->y;    vec++;    for ( ; vec < limit; vec++ )    {      TPos  x = vec->x;      TPos  y = vec->y;      if ( x < ras.min_ex ) ras.min_ex = x;      if ( x > ras.max_ex ) ras.max_ex = x;      if ( y < ras.min_ey ) ras.min_ey = y;      if ( y > ras.max_ey ) ras.max_ey = y;    }    /* truncate the bounding box to integer pixels */    ras.min_ex = ras.min_ex >> 6;    ras.min_ey = ras.min_ey >> 6;    ras.max_ex = ( ras.max_ex + 63 ) >> 6;    ras.max_ey = ( ras.max_ey + 63 ) >> 6;  }  /*************************************************************************/  /*                                                                       */  /* Record the current cell in the table.                                 */  /*                                                                       */  static  int  record_cell( RAS_ARG )  {    PCell  cell;    if ( !ras.invalid && ( ras.area | ras.cover ) )    {      if ( ras.num_cells >= ras.max_cells )        return 1;      cell        = ras.cells + ras.num_cells++;      cell->x     = ras.ex - ras.min_ex;      cell->y     = ras.ey - ras.min_ey;      cell->area  = ras.area;      cell->cover = ras.cover;    }    return 0;  }  /*************************************************************************/  /*                                                                       */  /* Set the current cell to a new position.                               */  /*                                                                       */  static  int  set_cell( RAS_ARG_ TScan  ex,                          TScan  ey )  {    int  invalid, record, clean;    /* Move the cell pointer to a new position.  We set the `invalid'      */    /* flag to indicate that the cell isn't part of those we're interested */    /* in during the render phase.  This means that:                       */    /*                                                                     */    /* . the new vertical position must be within min_ey..max_ey-1.        */    /* . the new horizontal position must be strictly less than max_ex     */    /*                                                                     */    /* Note that if a cell is to the left of the clipping region, it is    */    /* actually set to the (min_ex-1) horizontal position.                 */    record  = 0;    clean   = 1;    invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );    if ( !invalid )    {      /* All cells that are on the left of the clipping region go to the */      /* min_ex - 1 horizontal position.                                 */      if ( ex < ras.min_ex )        ex = ras.min_ex - 1;      /* if our position is new, then record the previous cell */      if ( ex != ras.ex || ey != ras.ey )        record = 1;      else        clean = ras.invalid;  /* do not clean if we didn't move from */                              /* a valid cell                        */    }    /* record the previous cell if needed (i.e., if we changed the cell */    /* position, of changed the `invalid' flag)                         */    if ( ( ras.invalid != invalid || record ) && record_cell( RAS_VAR ) )      return 1;    if ( clean )    {      ras.area  = 0;      ras.cover = 0;    }    ras.invalid = invalid;    ras.ex      = ex;    ras.ey      = ey;    return 0;  }  /*************************************************************************/  /*                                                                       */  /* Start a new contour at a given cell.                                  */  /*                                                                       */  static  void  start_cell( RAS_ARG_  TScan  ex,                              TScan  ey )  {    if ( ex < ras.min_ex )      ex = ras.min_ex - 1;    ras.area    = 0;    ras.cover   = 0;    ras.ex      = ex;    ras.ey      = ey;    ras.last_ey = SUBPIXELS( ey );    ras.invalid = 0;    (void)set_cell( RAS_VAR_ ex, ey );  }  /*************************************************************************/  /*                                                                       */  /* Render a scanline as one or more cells.                               */  /*                                                                       */  static  int  render_scanline( RAS_ARG_  TScan  ey,                                  TPos   x1,                                  TScan  y1,                                  TPos   x2,                                  TScan  y2 )  {    TScan  ex1, ex2, fx1, fx2, delta;    long   p, first, dx;    int    incr, lift, mod, rem;    dx = x2 - x1;    ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */    ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */    fx1 = x1 - SUBPIXELS( ex1 );    fx2 = x2 - SUBPIXELS( ex2 );    /* trivial case.  Happens often */    if ( y1 == y2 )      return set_cell( RAS_VAR_ ex2, ey );    /* everything is located in a single cell.  That is easy! */    /*                                                        */    if ( ex1 == ex2 )    {      delta      = y2 - y1;      ras.area  += ( fx1 + fx2 ) * delta;      ras.cover += delta;      return 0;    }    /* ok, we'll have to render a run of adjacent cells on the same */    /* scanline...                                                  */    /*                                                              */    p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );    first = ONE_PIXEL;    incr  = 1;    if ( dx < 0 )    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -