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

📄 ftgrays.c

📁 智能设备中PDF阅读器的源码!用于windows mobile2003或者WM5以上
💻 C
📖 第 1 页 / 共 4 页
字号:
      {
        for ( j = i - gap; ; j -= gap )
        {
          PCell  k = j + gap;


          if ( LESS_THAN( j, k ) )
            break;

          SWAP_CELLS( j, k, temp );

          if ( j < cells + gap )
            break;
        }
      }
    }
  }

#endif /* SHELL_SORT */


#ifdef QUICK_SORT

  /* This is a non-recursive quicksort that directly process our cells     */
  /* array.  It should be faster than calling the stdlib qsort(), and we   */
  /* can even tailor our insertion threshold...                            */

#define QSORT_THRESHOLD  9  /* below this size, a sub-array will be sorted */
                            /* through a normal insertion sort             */

  static void
  gray_quick_sort( PCell  cells,
                   int    count )
  {
    PCell   stack[40];  /* should be enough ;-) */
    PCell*  top;        /* top of stack */
    PCell   base, limit;
    TCell   temp;


    limit = cells + count;
    base  = cells;
    top   = stack;

    for (;;)
    {
      int    len = (int)( limit - base );
      PCell  i, j, pivot;


      if ( len > QSORT_THRESHOLD )
      {
        /* we use base + len/2 as the pivot */
        pivot = base + len / 2;
        SWAP_CELLS( base, pivot, temp );

        i = base + 1;
        j = limit - 1;

        /* now ensure that *i <= *base <= *j */
        if ( LESS_THAN( j, i ) )
          SWAP_CELLS( i, j, temp );

        if ( LESS_THAN( base, i ) )
          SWAP_CELLS( base, i, temp );

        if ( LESS_THAN( j, base ) )
          SWAP_CELLS( base, j, temp );

        for (;;)
        {
          do i++; while ( LESS_THAN( i, base ) );
          do j--; while ( LESS_THAN( base, j ) );

          if ( i > j )
            break;

          SWAP_CELLS( i, j, temp );
        }

        SWAP_CELLS( base, j, temp );

        /* now, push the largest sub-array */
        if ( j - base > limit - i )
        {
          top[0] = base;
          top[1] = j;
          base   = i;
        }
        else
        {
          top[0] = i;
          top[1] = limit;
          limit  = j;
        }
        top += 2;
      }
      else
      {
        /* the sub-array is small, perform insertion sort */
        j = base;
        i = j + 1;

        for ( ; i < limit; j = i, i++ )
        {
          for ( ; LESS_THAN( j + 1, j ); j-- )
          {
            SWAP_CELLS( j + 1, j, temp );
            if ( j == base )
              break;
          }
        }
        if ( top > stack )
        {
          top  -= 2;
          base  = top[0];
          limit = top[1];
        }
        else
          break;
      }
    }
  }

#endif /* QUICK_SORT */


#ifdef DEBUG_GRAYS
#ifdef DEBUG_SORT

  static int
  gray_check_sort( PCell  cells,
                   int    count )
  {
    PCell  p, q;


    for ( p = cells + count - 2; p >= cells; p-- )
    {
      q = p + 1;
      if ( !LESS_THAN( p, q ) )
        return 0;
    }
    return 1;
  }

#endif /* DEBUG_SORT */
#endif /* DEBUG_GRAYS */


  static int
  gray_move_to( const FT_Vector*  to,
                FT_Raster         raster )
  {
    TPos  x, y;


    /* record current cell, if any */
    gray_record_cell( (PRaster)raster );

    /* start to a new position */
    x = UPSCALE( to->x );
    y = UPSCALE( to->y );

    gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );

    ((PRaster)raster)->x = x;
    ((PRaster)raster)->y = y;
    return 0;
  }


  static int
  gray_line_to( const FT_Vector*  to,
                FT_Raster         raster )
  {
    gray_render_line( (PRaster)raster,
                      UPSCALE( to->x ), UPSCALE( to->y ) );
    return 0;
  }


  static int
  gray_conic_to( const FT_Vector*  control,
                 const FT_Vector*  to,
                 FT_Raster         raster )
  {
    gray_render_conic( (PRaster)raster, control, to );
    return 0;
  }


  static int
  gray_cubic_to( const FT_Vector*  control1,
                 const FT_Vector*  control2,
                 const FT_Vector*  to,
                 FT_Raster         raster )
  {
    gray_render_cubic( (PRaster)raster, control1, control2, to );
    return 0;
  }


  static void
  gray_render_span( int             y,
                    int             count,
                    const FT_Span*  spans,
                    PRaster         raster )
  {
    unsigned char*  p;
    FT_Bitmap*      map = &raster->target;


    /* first of all, compute the scanline offset */
    p = (unsigned char*)map->buffer - y * map->pitch;
    if ( map->pitch >= 0 )
      p += ( map->rows - 1 ) * map->pitch;

    for ( ; count > 0; count--, spans++ )
    {
      unsigned char  coverage = spans->coverage;


#ifdef GRAYS_USE_GAMMA
      coverage = raster->gamma[coverage];
#endif

      if ( coverage )
#if 1
        FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
#else /* 1 */
      {
        q     = p + spans->x;
        limit = q + spans->len;
        for ( ; q < limit; q++ )
          q[0] = (unsigned char)coverage;
      }
#endif /* 1 */
    }
  }


#ifdef DEBUG_GRAYS

#include <stdio.h>

  static void
  gray_dump_cells( RAS_ARG )
  {
    PCell  cell, limit;
    int    y = -1;


    cell  = ras.cells;
    limit = cell + ras.num_cells;

    for ( ; cell < limit; cell++ )
    {
      if ( cell->y != y )
      {
        fprintf( stderr, "\n%2d: ", cell->y );
        y = cell->y;
      }
      fprintf( stderr, "[%d %d %d]",
               cell->x, cell->area, cell->cover );
    }
    fprintf(stderr, "\n" );
  }

#endif /* DEBUG_GRAYS */


  static void
  gray_hline( RAS_ARG_ TCoord  x,
                       TCoord  y,
                       TPos    area,
                       int     acount )
  {
    FT_Span*   span;
    int        count;
    int        coverage;


    /* compute the coverage line's coverage, depending on the    */
    /* outline fill rule                                         */
    /*                                                           */
    /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
    /*                                                           */
    coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
                                                    /* use range 0..256 */
    if ( coverage < 0 )
      coverage = -coverage;

    if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
    {
      coverage &= 511;

      if ( coverage > 256 )
        coverage = 512 - coverage;
      else if ( coverage == 256 )
        coverage = 255;
    }
    else
    {
      /* normal non-zero winding rule */
      if ( coverage >= 256 )
        coverage = 255;
    }

    y += (TCoord)ras.min_ey;
    x += (TCoord)ras.min_ex;

    if ( coverage )
    {
      /* see if we can add this span to the current list */
      count = ras.num_gray_spans;
      span  = ras.gray_spans + count - 1;
      if ( count > 0                          &&
           ras.span_y == y                    &&
           (int)span->x + span->len == (int)x &&
           span->coverage == coverage )
      {
        span->len = (unsigned short)( span->len + acount );
        return;
      }

      if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
      {
        if ( ras.render_span && count > 0 )
          ras.render_span( ras.span_y, count, ras.gray_spans,
                           ras.render_span_data );
        /* ras.render_span( span->y, ras.gray_spans, count ); */

#ifdef DEBUG_GRAYS

        if ( ras.span_y >= 0 )
        {
          int  n;


          fprintf( stderr, "y=%3d ", ras.span_y );
          span = ras.gray_spans;
          for ( n = 0; n < count; n++, span++ )
            fprintf( stderr, "[%d..%d]:%02x ",
                     span->x, span->x + span->len - 1, span->coverage );
          fprintf( stderr, "\n" );
        }

#endif /* DEBUG_GRAYS */

        ras.num_gray_spans = 0;
        ras.span_y         = y;

        count = 0;
        span  = ras.gray_spans;
      }
      else
        span++;

      /* add a gray span to the current list */
      span->x        = (short)x;
      span->len      = (unsigned short)acount;
      span->coverage = (unsigned char)coverage;
      ras.num_gray_spans++;
    }
  }


  static void
  gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
  {
    TCoord  x, y, cover;
    TArea   area;
    PCell   start, cur, limit;

    FT_UNUSED( target );


    if ( ras.num_cells == 0 )
      return;

    cur   = ras.cells;
    limit = cur + ras.num_cells;

    cover              = 0;
    ras.span_y         = -1;
    ras.num_gray_spans = 0;

    for (;;)
    {
      start  = cur;
      y      = start->y;
      x      = start->x;

      area   = start->area;
      cover += start->cover;

      /* accumulate all start cells */
      for (;;)
      {
        ++cur;
        if ( cur >= limit || cur->y != start->y || cur->x != start->x )
          break;

        area  += cur->area;
        cover += cur->cover;
      }

      /* if the start cell has a non-null area, we must draw an */
      /* individual gray pixel there                            */
      if ( area && x >= 0 )
      {
        gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
        x++;
      }

      if ( x < 0 )
        x = 0;

      if ( cur < limit && start->y == cur->y )
      {
        /* draw a gray span between the start cell and the current one */
        if ( cur->x > x )
          gray_hline( RAS_VAR_ x, y,
                      cover * ( ONE_PIXEL * 2 ), cur->x - x );
      }
      else
      {
        /* draw a gray span until the end of the clipping region */
        if ( cover && x < ras.max_ex - ras.min_ex )
          gray_hline( RAS_VAR_ x, y,
                      cover * ( ONE_PIXEL * 2 ),
                      (int)( ras.max_ex - x - ras.min_ex ) );
        cover = 0;
      }

      if ( cur >= limit )
        break;
    }

    if ( ras.render_span && ras.num_gray_spans > 0 )
      ras.render_span( ras.span_y, ras.num_gray_spans,
                       ras.gray_spans, ras.render_span_data );

#ifdef DEBUG_GRAYS

    {
      int       n;
      FT_Span*  span;


      fprintf( stderr, "y=%3d ", ras.span_y );
      span = ras.gray_spans;
      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
        fprintf( stderr, "[%d..%d]:%02x ",
                 span->x, span->x + span->len - 1, span->coverage );
      fprintf( stderr, "\n" );
    }

#endif /* DEBUG_GRAYS */

  }


#ifdef _STANDALONE_

  /*************************************************************************/
  /*                                                                       */
  /*  The following function should only compile in stand_alone mode,      */
  /*  i.e., when building this component without the rest of FreeType.     */
  /*                                                                       */
  /*************************************************************************/

  /*************************************************************************/
  /*                                                                       */
  /* <Function>                                                            */
  /*    FT_Outline_Decompose                                               */
  /*                                                                       */
  /* <Description>                                                         */
  /*    Walks over an outline's structure to decompose it into individual  */
  /*    segments and Bezier arcs.  This function is also able to emit      */
  /*    `move to' and `close to' operations to indicate the start and end  */
  /*    of new contours in the outline.                                    */
  /*                                                                       */
  /* <Input>                                                               */
  /*    outline        :: A pointer to the source target.                  */
  /*                                                                       */
  /*    func_interface :: A table of `emitters', i.e,. function pointers   */
  /*                      called during decomposition to indicate path     */
  /*                      operations.                                      */
  /*                                                                       */
  /*    user           :: A typeless pointer which is passed to each       */
  /*                      emitter during the decomposition.  It can be     */
  /*                      used to store the state during the               */
  /*                      decomposition.                                   */
  /*                                                                       */
  /* <Return>                                                              */
  /*    Error code.  0 means sucess.                                       */
  /*                                                                       */
  static
  int  FT_Outline_Decompose( const FT_Outline*        outline,
                             const FT_Outline_Funcs*  func_interface,
                             void*                    user )
  {
#undef SCALED
#if 0
#define SCALED( x )  ( ( (x) << shift ) - delta )
#else
#define SCALED( x )  (x)
#endif

    FT_Vector   v_last;
    FT_Vector   v_control;
    FT_Vector   v_start;

    FT_Vector*  point;
    FT_Vector*  limit;
    char*       tags;

    int   n;         /* index of contour in outline     */
    int   first;     /* index of first point in contour */
    int   error;
    char  tag;       /* current point's state           */

#if 0
    int   shift = func_interface->shift;
    TPos  delta = func_interface->delta;
#endif


    first = 0;

    for ( n = 0; n < outline->n_contours; n++ )
    {
      int  last;  /* index of last point in contour */


      last  = outline->contours[n];
      limit = outline->points + last;

⌨️ 快捷键说明

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