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

📄 pshalgo.c

📁 奇趣公司比较新的qt/emd版本
💻 C
📖 第 1 页 / 共 4 页
字号:
                 *    new_pos = left                 * else                 *    new_pos = right                 */                FT_Pos  left_nearest  = FT_PIX_ROUND( pos );                FT_Pos  right_nearest = FT_PIX_ROUND( pos + len );                FT_Pos  left_disp     = left_nearest - pos;                FT_Pos  right_disp    = right_nearest - ( pos + len );                if ( left_disp < 0 )                  left_disp = -left_disp;                if ( right_disp < 0 )                  right_disp = -right_disp;                if ( left_disp <= right_disp )                  pos = left_nearest;                else                  pos = right_nearest;              }              else              {                /* this is a ghost stem; we simply round it */                pos = FT_PIX_ROUND( pos );              }            }            else            {              len = psh_dimension_quantize_len( dim, len, 0 );            }          }          /* now that we have a good hinted stem width, try to position */          /* the stem along a pixel grid integer coordinate             */          hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len );          hint->cur_len = len;        }      }      if ( do_snapping )      {        pos = hint->cur_pos;        len = hint->cur_len;        if ( len < 64 )          len = 64;        else          len = FT_PIX_ROUND( len );        switch ( align.align )        {          case PSH_BLUE_ALIGN_TOP:            hint->cur_pos = align.align_top - len;            hint->cur_len = len;            break;          case PSH_BLUE_ALIGN_BOT:            hint->cur_len = len;            break;          case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:            /* don't touch */            break;          default:            hint->cur_len = len;            if ( len & 64 )              pos = FT_PIX_FLOOR( pos + ( len >> 1 ) ) + 32;            else              pos = FT_PIX_ROUND( pos + ( len >> 1 ) );            hint->cur_pos = pos - ( len >> 1 );            hint->cur_len = len;        }      }      psh_hint_set_fitted( hint );#ifdef DEBUG_HINTER      if ( ps_debug_hint_func )        ps_debug_hint_func( hint, dimension );#endif    }  }#if 0  /* not used for now, experimental */ /*  *  A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)  *  of stems  */  static void  psh_hint_align_light( PSH_Hint     hint,                        PSH_Globals  globals,                        FT_Int       dimension,                        PSH_Glyph    glyph )  {    PSH_Dimension  dim   = &globals->dimension[dimension];    FT_Fixed       scale = dim->scale_mult;    FT_Fixed       delta = dim->scale_delta;    if ( !psh_hint_is_fitted( hint ) )    {      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;      FT_Pos  len = FT_MulFix( hint->org_len, scale );      FT_Pos  fit_len;      PSH_AlignmentRec  align;      /* ignore stem alignments when requested through the hint flags */      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||           ( dimension == 1 && !glyph->do_vert_hints ) )      {        hint->cur_pos = pos;        hint->cur_len = len;        psh_hint_set_fitted( hint );        return;      }      fit_len = len;      hint->cur_len = fit_len;      /* check blue zones for horizontal stems */      align.align = PSH_BLUE_ALIGN_NONE;      align.align_bot = align.align_top = 0;      if ( dimension == 1 )        psh_blues_snap_stem( &globals->blues,                             hint->org_pos + hint->org_len,                             hint->org_pos,                             &align );      switch ( align.align )      {      case PSH_BLUE_ALIGN_TOP:        /* the top of the stem is aligned against a blue zone */        hint->cur_pos = align.align_top - fit_len;        break;      case PSH_BLUE_ALIGN_BOT:        /* the bottom of the stem is aligned against a blue zone */        hint->cur_pos = align.align_bot;        break;      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:        /* both edges of the stem are aligned against blue zones */        hint->cur_pos = align.align_bot;        hint->cur_len = align.align_top - align.align_bot;        break;      default:        {          PSH_Hint  parent = hint->parent;          if ( parent )          {            FT_Pos  par_org_center, par_cur_center;            FT_Pos  cur_org_center, cur_delta;            /* ensure that parent is already fitted */            if ( !psh_hint_is_fitted( parent ) )              psh_hint_align_light( parent, globals, dimension, glyph );            par_org_center = parent->org_pos + ( parent->org_len / 2 );            par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );            cur_org_center = hint->org_pos   + ( hint->org_len   / 2 );            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );            pos       = par_cur_center + cur_delta - ( len >> 1 );          }          /* Stems less than one pixel wide are easy -- we want to           * make them as dark as possible, so they must fall within           * one pixel.  If the stem is split between two pixels           * then snap the edge that is nearer to the pixel boundary           * to the pixel boundary.           */          if ( len <= 64 )          {            if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )              pos += psh_hint_snap_stem_side_delta ( pos, len );          }          /* Position stems other to minimize the amount of mid-grays.           * There are, in general, two positions that do this,           * illustrated as A) and B) below.           *           *   +                   +                   +                   +           *           * A)             |--------------------------------|           * B)   |--------------------------------|           * C)       |--------------------------------|           *           * Position A) (split the excess stem equally) should be better           * for stems of width N + f where f < 0.5.           *           * Position B) (split the deficiency equally) should be better           * for stems of width N + f where f > 0.5.           *           * It turns out though that minimizing the total number of lit           * pixels is also important, so position C), with one edge           * aligned with a pixel boundary is actually preferable           * to A).  There are also more possibile positions for C) than           * for A) or B), so it involves less distortion of the overall           * character shape.           */          else /* len > 64 */          {            FT_Fixed  frac_len = len & 63;            FT_Fixed  center = pos + ( len >> 1 );            FT_Fixed  delta_a, delta_b;            if ( ( len / 64 ) & 1 )            {              delta_a = FT_PIX_FLOOR( center ) + 32 - center;              delta_b = FT_PIX_ROUND( center ) - center;            }            else            {              delta_a = FT_PIX_ROUND( center ) - center;              delta_b = FT_PIX_FLOOR( center ) + 32 - center;            }            /* We choose between B) and C) above based on the amount             * of fractinal stem width; for small amounts, choose             * C) always, for large amounts, B) always, and inbetween,             * pick whichever one involves less stem movement.             */            if ( frac_len < 32 )            {              pos += psh_hint_snap_stem_side_delta ( pos, len );            }            else if ( frac_len < 48 )            {              FT_Fixed  side_delta = psh_hint_snap_stem_side_delta ( pos,                                                                     len );              if ( FT_ABS( side_delta ) < FT_ABS( delta_b ) )                pos += side_delta;              else                pos += delta_b;            }            else            {              pos += delta_b;            }          }          hint->cur_pos = pos;        }      }  /* switch */      psh_hint_set_fitted( hint );#ifdef DEBUG_HINTER      if ( ps_debug_hint_func )        ps_debug_hint_func( hint, dimension );#endif    }  }#endif /* 0 */  static void  psh_hint_table_align_hints( PSH_Hint_Table  table,                              PSH_Globals     globals,                              FT_Int          dimension,                              PSH_Glyph       glyph )  {    PSH_Hint       hint;    FT_UInt        count;#ifdef DEBUG_HINTER    PSH_Dimension  dim   = &globals->dimension[dimension];    FT_Fixed       scale = dim->scale_mult;    FT_Fixed       delta = dim->scale_delta;    if ( ps_debug_no_vert_hints && dimension == 0 )    {      ps_simple_scale( table, scale, delta, dimension );      return;    }    if ( ps_debug_no_horz_hints && dimension == 1 )    {      ps_simple_scale( table, scale, delta, dimension );      return;    }#endif /* DEBUG_HINTER*/    hint  = table->hints;    count = table->max_hints;    for ( ; count > 0; count--, hint++ )      psh_hint_align( hint, globals, dimension, glyph );  }  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                POINTS INTERPOLATION ROUTINES                  *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/#define PSH_ZONE_MIN  -3200000L#define PSH_ZONE_MAX  +3200000L#define xxDEBUG_ZONES#ifdef DEBUG_ZONES#include <stdio.h>  static void  psh_print_zone( PSH_Zone  zone )  {    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",             zone->scale / 65536.0,             zone->delta / 64.0,             zone->min,             zone->max );  }#else#define psh_print_zone( x )  do { } while ( 0 )#endif /* DEBUG_ZONES */  /*************************************************************************/  /*************************************************************************/  /*****                                                               *****/  /*****                    HINTER GLYPH MANAGEMENT                    *****/  /*****                                                               *****/  /*************************************************************************/  /*************************************************************************/#if 1#define  psh_corner_is_flat      ft_corner_is_flat#define  psh_corner_orientation  ft_corner_orientation#else  FT_LOCAL_DEF( FT_Int )  psh_corner_is_flat( FT_Pos  x_in,                      FT_Pos  y_in,                      FT_Pos  x_out,                      FT_Pos  y_out )  {    FT_Pos  ax = x_in;    FT_Pos  ay = y_in;    FT_Pos  d_in, d_out, d_corner;    if ( ax < 0 )      ax = -ax;    if ( ay < 0 )      ay = -ay;    d_in = ax + ay;    ax = x_out;    if ( ax < 0 )      ax = -ax;    ay = y_out;    if ( ay < 0 )      ay = -ay;    d_out = ax + ay;    ax = x_out + x_in;    if ( ax < 0 )      ax = -ax;    ay = y_out + y_in;    if ( ay < 0 )      ay = -ay;    d_corner = ax + ay;    return ( d_in + d_out - d_corner ) < ( d_corner >> 4 );  }  static FT_Int  psh_corner_orientation( FT_Pos  in_x,                          FT_Pos  in_y,                          FT_Pos  out_x,                          FT_Pos  out_y )  {    FT_Int  result;    /* deal with the trivial cases quickly */    if ( in_y == 0 )    {      if ( in_x >= 0 )        result = out_y;      else        result = -out_y;    }    else if ( in_x == 0 )    {      if ( in_y >= 0 )        result = -out_x;      else        result = out_x;    }    else if ( out_y == 0 )    {      if ( out_x >= 0 )        result = in_y;      else        result = -in_y;    }    else if ( out_x == 0 )    {      if ( out_y >= 0 )        result = -in_x;      else        result =  in_x;    }    else /* general case */    {      long long  delta = (long long)in_x * out_y - (long long)in_y * out_x;      if ( delta == 0 )        result = 0;      else        result = 1 - 2 * ( delta < 0 );    }    return result;  }#endif /* !1 */#ifdef COMPUTE_INFLEXS  /* compute all inflex points in a given glyph */  static void  psh_glyph_compute_inflections( PSH_Glyph  glyph )  {    FT_UInt  n;    for ( n = 0; n < glyph->num_contours; n++ )    {      PSH_Point  first, start, end, before, after;      FT_Pos     in_x, in_y, out_x, out_y;      FT_Int     orient_prev, orient_cur;      FT_Int     finished = 0;      /* we need at least 4 points to create an inflection point */      if ( glyph->contours[n].count < 4 )        continue;      /* compute first segment in contour */      first = glyph->contours[n].start;      start = end = first;      do      {        end = end->next;        if ( end == first )          goto Skip;        in_x = end->org_u - start->org_u;        in_y = end->org_v - start->org_v;      } 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->org_u - before->org_u;          out_y = start->org_v - before->org_v;        } while ( out_x == 0 && out_y == 0 );        orient_prev = psh_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        {          do          {            end   = after;            after = after->next;            if ( after == first )              finished = 1;            out_x = after->org_u - end->org_u;            out_y = after->org_v - end->org_v;          } while ( out_x == 0 && out_y == 0 );          orient_cur = psh_corner_orientation( in_x, in_y, out_x, out_y );        } while ( orient_cur == 0 );        if ( ( orient_cur ^ orient_prev ) < 0 )        {          do          {            psh_point_set_inflex( start );            start = start->next;          }          while ( start != end );          psh_point_set_inflex( start );        }        start       = end;        end         = after;        orient_prev = orient_cur;        in_x        = out_x;        in_y        = out_y;      } while ( !finished );    Skip:      ;    }  }#endif /* COMPUTE_INFLEXS */  static void  psh_glyph_done( PSH_Glyph  glyph )  {    FT_Memory  memory = glyph->memory;    psh_hint_table_done( &glyph->hint_tables[1], memory );    psh_hint_table_done( &glyph->hint_tables[0], memory );    FT_FREE( glyph->points );

⌨️ 快捷键说明

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