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

📄 pshalgo.c

📁 奇趣公司比较新的qt/emd版本
💻 C
📖 第 1 页 / 共 4 页
字号:
    FT_FREE( glyph->contours );    glyph->num_points   = 0;    glyph->num_contours = 0;    glyph->memory = 0;  }  static int  psh_compute_dir( FT_Pos  dx,                   FT_Pos  dy )  {    FT_Pos  ax, ay;    int     result = PSH_DIR_NONE;    ax = ( dx >= 0 ) ? dx : -dx;    ay = ( dy >= 0 ) ? dy : -dy;    if ( ay * 12 < ax )    {      /* |dy| <<< |dx|  means a near-horizontal segment */      result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;    }    else if ( ax * 12 < ay )    {      /* |dx| <<< |dy|  means a near-vertical segment */      result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;    }    return result;  }  /* load outline point coordinates into hinter glyph */  static void  psh_glyph_load_points( PSH_Glyph  glyph,                         FT_Int     dimension )  {    FT_Vector*  vec   = glyph->outline->points;    PSH_Point   point = glyph->points;    FT_UInt     count = glyph->num_points;    for ( ; count > 0; count--, point++, vec++ )    {      point->flags2 = 0;      point->hint   = NULL;      if ( dimension == 0 )      {        point->org_u = vec->x;        point->org_v = vec->y;      }      else      {        point->org_u = vec->y;        point->org_v = vec->x;      }#ifdef DEBUG_HINTER      point->org_x = vec->x;      point->org_y = vec->y;#endif    }  }  /* save hinted point coordinates back to outline */  static void  psh_glyph_save_points( PSH_Glyph  glyph,                         FT_Int     dimension )  {    FT_UInt     n;    PSH_Point   point = glyph->points;    FT_Vector*  vec   = glyph->outline->points;    char*       tags  = glyph->outline->tags;    for ( n = 0; n < glyph->num_points; n++ )    {      if ( dimension == 0 )        vec[n].x = point->cur_u;      else        vec[n].y = point->cur_u;      if ( psh_point_is_strong( point ) )        tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );#ifdef DEBUG_HINTER      if ( dimension == 0 )      {        point->cur_x   = point->cur_u;        point->flags_x = point->flags2 | point->flags;      }      else      {        point->cur_y   = point->cur_u;        point->flags_y = point->flags2 | point->flags;      }#endif      point++;    }  }  static FT_Error  psh_glyph_init( PSH_Glyph    glyph,                  FT_Outline*  outline,                  PS_Hints     ps_hints,                  PSH_Globals  globals )  {    FT_Error   error;    FT_Memory  memory;    /* clear all fields */    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );    memory = glyph->memory = globals->memory;    /* allocate and setup points + contours arrays */    if ( FT_NEW_ARRAY( glyph->points,   outline->n_points   ) ||         FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )      goto Exit;    glyph->num_points   = outline->n_points;    glyph->num_contours = outline->n_contours;    {      FT_UInt      first = 0, next, n;      PSH_Point    points  = glyph->points;      PSH_Contour  contour = glyph->contours;      for ( n = 0; n < glyph->num_contours; n++ )      {        FT_Int     count;        PSH_Point  point;        next  = outline->contours[n] + 1;        count = next - first;        contour->start = points + first;        contour->count = (FT_UInt)count;        if ( count > 0 )        {          point = points + first;          point->prev    = points + next - 1;          point->contour = contour;          for ( ; count > 1; count-- )          {            point[0].next = point + 1;            point[1].prev = point;            point++;            point->contour = contour;          }          point->next = points + first;        }        contour++;        first = next;      }    }    {      PSH_Point   points = glyph->points;      PSH_Point   point  = points;      FT_Vector*  vec    = outline->points;      FT_UInt     n;      for ( n = 0; n < glyph->num_points; n++, point++ )      {        FT_Int  n_prev = (FT_Int)( point->prev - points );        FT_Int  n_next = (FT_Int)( point->next - points );        FT_Pos  dxi, dyi, dxo, dyo;        if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )          point->flags = PSH_POINT_OFF;        dxi = vec[n].x - vec[n_prev].x;        dyi = vec[n].y - vec[n_prev].y;        point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );        dxo = vec[n_next].x - vec[n].x;        dyo = vec[n_next].y - vec[n].y;        point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );        /* detect smooth points */        if ( point->flags & PSH_POINT_OFF )          point->flags |= PSH_POINT_SMOOTH;        else if ( point->dir_in == point->dir_out )        {          if ( point->dir_out != PSH_DIR_NONE           ||               psh_corner_is_flat( dxi, dyi, dxo, dyo ) )            point->flags |= PSH_POINT_SMOOTH;        }      }    }    glyph->outline = outline;    glyph->globals = globals;#ifdef COMPUTE_INFLEXS    psh_glyph_load_points( glyph, 0 );    psh_glyph_compute_inflections( glyph );#endif /* COMPUTE_INFLEXS */    /* now deal with hints tables */    error = psh_hint_table_init( &glyph->hint_tables [0],                                 &ps_hints->dimension[0].hints,                                 &ps_hints->dimension[0].masks,                                 &ps_hints->dimension[0].counters,                                 memory );    if ( error )      goto Exit;    error = psh_hint_table_init( &glyph->hint_tables [1],                                 &ps_hints->dimension[1].hints,                                 &ps_hints->dimension[1].masks,                                 &ps_hints->dimension[1].counters,                                 memory );    if ( error )      goto Exit;  Exit:    return error;  }  /* compute all extrema in a glyph for a given dimension */  static void  psh_glyph_compute_extrema( PSH_Glyph  glyph )  {    FT_UInt  n;    /* first of all, compute all local extrema */    for ( n = 0; n < glyph->num_contours; n++ )    {      PSH_Point  first = glyph->contours[n].start;      PSH_Point  point, before, after;      if ( glyph->contours[n].count == 0 )        continue;      point  = first;      before = point;      after  = point;      do      {        before = before->prev;        if ( before == first )          goto Skip;      } while ( before->org_u == point->org_u );      first = point = before->next;      for (;;)      {        after = point;        do        {          after = after->next;          if ( after == first )            goto Next;        } while ( after->org_u == point->org_u );        if ( before->org_u < point->org_u )        {          if ( after->org_u < point->org_u )          {            /* local maximum */            goto Extremum;          }        }        else /* before->org_u > point->org_u */        {          if ( after->org_u > point->org_u )          {            /* local minimum */          Extremum:            do            {              psh_point_set_extremum( point );              point = point->next;            } while ( point != after );          }        }        before = after->prev;        point  = after;      } /* for  */    Next:      ;    }    /* for each extremum, determine its direction along the */    /* orthogonal axis                                      */    for ( n = 0; n < glyph->num_points; n++ )    {      PSH_Point  point, before, after;      point  = &glyph->points[n];      before = point;      after  = point;      if ( psh_point_is_extremum( point ) )      {        do        {          before = before->prev;          if ( before == point )            goto Skip;        } while ( before->org_v == point->org_v );        do        {          after = after->next;          if ( after == point )            goto Skip;        } while ( after->org_v == point->org_v );      }      if ( before->org_v < point->org_v &&           after->org_v  > point->org_v )      {        psh_point_set_positive( point );      }      else if ( before->org_v > point->org_v &&                after->org_v  < point->org_v )      {        psh_point_set_negative( point );      }    Skip:      ;    }  }  /* major_dir is the direction for points on the bottom/left of the stem; */  /* Points on the top/right of the stem will have a direction of          */  /* -major_dir.                                                           */  static void  psh_hint_table_find_strong_points( PSH_Hint_Table  table,                                     PSH_Point       point,                                     FT_UInt         count,                                     FT_Int          threshold,                                     FT_Int          major_dir )  {    PSH_Hint*  sort      = table->sort;    FT_UInt    num_hints = table->num_hints;    for ( ; count > 0; count--, point++ )    {      FT_Int  point_dir = 0;      FT_Pos  org_u     = point->org_u;      if ( psh_point_is_strong( point ) )        continue;      if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )        point_dir = point->dir_in;      else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )        point_dir = point->dir_out;      if ( point_dir )      {        if ( point_dir == major_dir )        {          FT_UInt  nn;          for ( nn = 0; nn < num_hints; nn++ )          {            PSH_Hint  hint = sort[nn];            FT_Pos    d    = org_u - hint->org_pos;            if ( d < threshold && -d < threshold )            {              psh_point_set_strong( point );              point->flags2 |= PSH_POINT_EDGE_MIN;              point->hint    = hint;              break;            }          }        }        else if ( point_dir == -major_dir )        {          FT_UInt  nn;          for ( nn = 0; nn < num_hints; nn++ )          {            PSH_Hint  hint = sort[nn];            FT_Pos    d    = org_u - hint->org_pos - hint->org_len;            if ( d < threshold && -d < threshold )            {              psh_point_set_strong( point );              point->flags2 |= PSH_POINT_EDGE_MAX;              point->hint    = hint;              break;            }          }        }      }#if 1      else if ( psh_point_is_extremum( point ) )      {        /* treat extrema as special cases for stem edge alignment */        FT_UInt  nn, min_flag, max_flag;        if ( major_dir == PSH_DIR_HORIZONTAL )        {          min_flag = PSH_POINT_POSITIVE;          max_flag = PSH_POINT_NEGATIVE;        }        else        {          min_flag = PSH_POINT_NEGATIVE;          max_flag = PSH_POINT_POSITIVE;        }        if ( point->flags2 & min_flag )        {          for ( nn = 0; nn < num_hints; nn++ )          {            PSH_Hint  hint = sort[nn];            FT_Pos    d    = org_u - hint->org_pos;            if ( d < threshold && -d < threshold )            {              point->flags2 |= PSH_POINT_EDGE_MIN;              point->hint    = hint;              psh_point_set_strong( point );              break;            }          }        }        else if ( point->flags2 & max_flag )        {          for ( nn = 0; nn < num_hints; nn++ )          {            PSH_Hint  hint = sort[nn];            FT_Pos    d    = org_u - hint->org_pos - hint->org_len;            if ( d < threshold && -d < threshold )            {              point->flags2 |= PSH_POINT_EDGE_MAX;              point->hint    = hint;              psh_point_set_strong( point );              break;            }          }        }        if ( point->hint == NULL )        {          for ( nn = 0; nn < num_hints; nn++ )          {            PSH_Hint  hint = sort[nn];            if ( org_u >= hint->org_pos                 &&                org_u <= hint->org_pos + hint->org_len )            {              point->hint = hint;              break;            }          }        }      }#endif /* 1 */    }  }  /* the accepted shift for strong points in fractional pixels */#define PSH_STRONG_THRESHOLD  32  /* the maximum shift value in font units */#define PSH_STRONG_THRESHOLD_MAXIMUM  30  /* find strong points in a glyph */  static void  psh_glyph_find_strong_points( PSH_Glyph  glyph,                                FT_Int     dimension )  {    /* a point is `strong' if it is located on a stem edge and       */    /* has an `in' or `out' tangent parallel to the hint's direction */    PSH_Hint_Table  table     = &glyph->hint_tables[dimension];    PS_Mask         mask      = table->hint_masks->masks;    FT_UInt         num_masks = table->hint_masks->num_masks;    FT_UInt         first     = 0;    FT_Int          major_dir = dimension == 0 ? PSH_DIR_VERTICAL                                               : PSH_DIR_HORIZONTAL;    PSH_Dimension   dim       = &glyph->globals->dimension[dimension];    FT_Fixed        scale     = dim->scale_mult;    FT_Int          threshold;    threshold = (FT_Int)FT_DivFix( PSH_STRONG_THRESHOLD, scale );    if ( threshold > PSH_STRONG_THRESHOLD_MAXIMUM )      threshold = PSH_STRONG_THRESHOLD_MAXIMUM;    /* process secondary hints to `selected' points */    if ( num_masks > 1 && glyph->num_points > 0 )    {      first = mask->end_point;      mask++;      for ( ; num_masks > 1; num_masks--, mask++ )      {        FT_UInt  next;        FT_Int   count;        next  = mask->end_point;        count = next - first;        if ( count > 0 )        {          PSH_Point  point = glyph->points + first;          psh_hint_table_activate_mask( table, mask );          psh_hint_table_find_strong_points( table, point, count,                                             threshold, major_dir );        }        first = next;      }    }    /* process primary hints for all points */    if ( num_masks == 1 )    {

⌨️ 快捷键说明

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