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

📄 afhints.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************/
/*                                                                         */
/*  afhints.c                                                              */
/*                                                                         */
/*    Auto-fitter hinting routines (body).                                 */
/*                                                                         */
/*  Copyright 2003, 2004, 2005, 2006, 2007 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.                                        */
/*                                                                         */
/***************************************************************************/


#include "afhints.h"
#include "aferrors.h"
#include FT_INTERNAL_CALC_H


  FT_LOCAL_DEF( FT_Error )
  af_axis_hints_new_segment( AF_AxisHints  axis,
                             FT_Memory     memory,
                             AF_Segment   *asegment )
  {
    FT_Error    error   = AF_Err_Ok;
    AF_Segment  segment = NULL;


    if ( axis->num_segments >= axis->max_segments )
    {
      FT_Int  old_max = axis->max_segments;
      FT_Int  new_max = old_max;
      FT_Int  big_max = FT_INT_MAX / sizeof ( *segment );


      if ( old_max >= big_max )
      {
        error = AF_Err_Out_Of_Memory;
        goto Exit;
      }

      new_max += ( new_max >> 2 ) + 4;
      if ( new_max < old_max || new_max > big_max )
        new_max = big_max;

      if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
        goto Exit;

      axis->max_segments = new_max;
    }

    segment = axis->segments + axis->num_segments++;
#if 0
    FT_ZERO( segment );
#endif

  Exit:
    *asegment = segment;
    return error;
  }


  FT_LOCAL( FT_Error )
  af_axis_hints_new_edge( AF_AxisHints  axis,
                          FT_Int        fpos,
                          FT_Memory     memory,
                          AF_Edge      *aedge )
  {
    FT_Error  error = AF_Err_Ok;
    AF_Edge   edge  = NULL;
    AF_Edge   edges;


    if ( axis->num_edges >= axis->max_edges )
    {
      FT_Int  old_max = axis->max_edges;
      FT_Int  new_max = old_max;
      FT_Int  big_max = FT_INT_MAX / sizeof ( *edge );


      if ( old_max >= big_max )
      {
        error = AF_Err_Out_Of_Memory;
        goto Exit;
      }

      new_max += ( new_max >> 2 ) + 4;
      if ( new_max < old_max || new_max > big_max )
        new_max = big_max;

      if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
        goto Exit;

      axis->max_edges = new_max;
    }

    edges = axis->edges;
    edge  = edges + axis->num_edges;

    while ( edge > edges && edge[-1].fpos > fpos )
    {
      edge[0] = edge[-1];
      edge--;
    }

    axis->num_edges++;

    FT_ZERO( edge );
    edge->fpos = (FT_Short)fpos;

  Exit:
    *aedge = edge;
    return error;
  }


#ifdef AF_DEBUG

#include <stdio.h>

  static const char*
  af_dir_str( AF_Direction  dir )
  {
    const char*  result;


    switch ( dir )
    {
    case AF_DIR_UP:
      result = "up";
      break;
    case AF_DIR_DOWN:
      result = "down";
      break;
    case AF_DIR_LEFT:
      result = "left";
      break;
    case AF_DIR_RIGHT:
      result = "right";
      break;
    default:
      result = "none";
    }

    return result;
  }


#define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )


  void
  af_glyph_hints_dump_points( AF_GlyphHints  hints )
  {
    AF_Point  points = hints->points;
    AF_Point  limit  = points + hints->num_points;
    AF_Point  point;


    printf( "Table of points:\n" );
    printf(   "  [ index |  xorg |  yorg |  xscale |  yscale "
              "|  xfit  |  yfit  |  flags ]\n" );

    for ( point = points; point < limit; point++ )
    {
      printf( "  [ %5d | %5d | %5d | %-5.2f | %-5.2f "
              "| %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
              point - points,
              point->fx,
              point->fy,
              point->ox/64.0,
              point->oy/64.0,
              point->x/64.0,
              point->y/64.0,
              ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
              ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
              ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
              ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
              ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
              ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' ');
    }
    printf( "\n" );
  }


  /* A function to dump the array of linked segments. */
  void
  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
  {
    FT_Int  dimension;


    for ( dimension = 1; dimension >= 0; dimension-- )
    {
      AF_AxisHints  axis     = &hints->axis[dimension];
      AF_Segment    segments = axis->segments;
      AF_Segment    limit    = segments + axis->num_segments;
      AF_Segment    seg;


      printf ( "Table of %s segments:\n",
               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
      printf ( "  [ index |  pos |  dir  | link | serif |"
               " height  | extra ]\n" );

      for ( seg = segments; seg < limit; seg++ )
      {
        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %5d | %5d ]\n",
                 seg - segments,
                 (int)seg->pos,
                 af_dir_str( (AF_Direction)seg->dir ),
                 AF_INDEX_NUM( seg->link, segments ),
                 AF_INDEX_NUM( seg->serif, segments ),
                 seg->height,
                 seg->height - ( seg->max_coord - seg->min_coord ) );
      }
      printf( "\n" );
    }
  }


  void
  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
  {
    FT_Int  dimension;


    for ( dimension = 1; dimension >= 0; dimension-- )
    {
      AF_AxisHints  axis  = &hints->axis[dimension];
      AF_Edge       edges = axis->edges;
      AF_Edge       limit = edges + axis->num_edges;
      AF_Edge       edge;


      /*
       *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
       *        since they have constant a X coordinate.
       */
      printf ( "Table of %s edges:\n",
               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
      printf ( "  [ index |  pos |  dir  | link |"
               " serif | blue | opos  |  pos  ]\n" );

      for ( edge = edges; edge < limit; edge++ )
      {
        printf ( "  [ %5d | %4d | %5s | %4d |"
                 " %5d |   %c  | %5.2f | %5.2f ]\n",
                 edge - edges,
                 (int)edge->fpos,
                 af_dir_str( (AF_Direction)edge->dir ),
                 AF_INDEX_NUM( edge->link, edges ),
                 AF_INDEX_NUM( edge->serif, edges ),
                 edge->blue_edge ? 'y' : 'n',
                 edge->opos / 64.0,
                 edge->pos / 64.0 );
      }
      printf( "\n" );
    }
  }

#else /* !AF_DEBUG */

  /* these empty stubs are only used to link the `ftgrid' test program */
  /* when debugging is disabled                                        */

  void
  af_glyph_hints_dump_points( AF_GlyphHints  hints )
  {
    FT_UNUSED( hints );
  }


  void
  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
  {
    FT_UNUSED( hints );
  }


  void
  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
  {
    FT_UNUSED( hints );
  }

#endif /* !AF_DEBUG */


  /* compute the direction value of a given vector */
  FT_LOCAL_DEF( AF_Direction )
  af_direction_compute( FT_Pos  dx,
                        FT_Pos  dy )
  {

#if 1

    FT_Pos        ll, ss;  /* long and short arm lengths */
    AF_Direction  dir;     /* candidate direction        */


    if ( dy >= dx )
    {
      if ( dy >= -dx )
      {
        dir = AF_DIR_UP;
        ll  = dy;
        ss  = dx;
      }
      else
      {
        dir = AF_DIR_LEFT;
        ll  = -dx;
        ss  = dy;
      }
    }
    else /* dy < dx */
    {
      if ( dy >= -dx )
      {
        dir = AF_DIR_RIGHT;
        ll  = dx;
        ss  = dy;
      }
      else
      {
        dir = AF_DIR_DOWN;
        ll  = dy;
        ss  = dx;
      }
    }

    ss *= 12;
    if ( FT_ABS(ll) <= FT_ABS(ss) )
      dir = AF_DIR_NONE;

    return dir;

#else /* 0 */

    AF_Direction  dir;
    FT_Pos        ax = FT_ABS( dx );
    FT_Pos        ay = FT_ABS( dy );


    dir = AF_DIR_NONE;

    /* atan(1/12) == 4.7 degrees */

    /* test for vertical direction */
    if ( ax * 12 < ay )
    {
      dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
    }
    /* test for horizontal direction */
    else if ( ay * 12 < ax )
    {
      dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
    }

    return dir;

#endif /* 0 */

  }


  /* compute all inflex points in a given glyph */

#if 1

  static void
  af_glyph_hints_compute_inflections( AF_GlyphHints  hints )
  {
    AF_Point*  contour       = hints->contours;
    AF_Point*  contour_limit = contour + hints->num_contours;


    /* do each contour separately */
    for ( ; contour < contour_limit; contour++ )
    {
      AF_Point  point = contour[0];
      AF_Point  first = point;
      AF_Point  start = point;
      AF_Point  end   = point;
      AF_Point  before;
      AF_Point  after;
      FT_Pos    in_x, in_y, out_x, out_y;
      AF_Angle  orient_prev, orient_cur;
      FT_Int    finished = 0;


      /* compute first segment in contour */
      first = point;

      start = end = first;
      do
      {
        end = end->next;
        if ( end == first )
          goto Skip;

        in_x = end->fx - start->fx;
        in_y = end->fy - start->fy;

      } while ( in_x == 0 && in_y == 0 );

      /* extend the segment start whenever possible */
      before = start;
      do
      {
        do
        {
          start  = before;
          before = before->prev;
          if ( before == first )
            goto Skip;

          out_x = start->fx - before->fx;
          out_y = start->fy - before->fy;

        } while ( out_x == 0 && out_y == 0 );

        orient_prev = ft_corner_orientation( in_x, in_y, out_x, out_y );

      } while ( orient_prev == 0 );

      first = start;

      in_x = out_x;
      in_y = out_y;

      /* now process all segments in the contour */
      do
      {
        /* first, extend current segment's end whenever possible */
        after = end;
        do

⌨️ 快捷键说明

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