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

📄 ahglyph.c

📁 a very goog book
💻 C
📖 第 1 页 / 共 3 页
字号:
              FT_Pos  min = seg1->min_coord;              FT_Pos  max = seg1->max_coord;              FT_Pos  len, dist, score;              if ( min < seg2->min_coord )                min = seg2->min_coord;              if ( max > seg2->max_coord )                max = seg2->max_coord;              len   = max - min;              dist  = seg2->pos - seg1->pos;              if ( dist < 0 )                dist = -dist;              if ( len < 8 )                score = 300*8 + dist - len*3;              else                score = dist + 300/len;              if ( score < best_score )              {                best_score   = score;                best_segment = seg2;              }            }          }        if ( best_segment )        {          seg1->link  = best_segment;          seg1->score = best_score;          best_segment->num_linked++;        }      } /* edges 1 */      /* now, compute the `serif' segments */      for ( seg1 = segments; seg1 < segment_limit; seg1++ )      {        seg2 = seg1->link;        if ( seg2 && seg2->link != seg1 )        {          seg1->link  = 0;          seg1->serif = seg2->link;        }      }      ah_setup_uv( outline, ah_uv_fxy );      segments      = outline->vert_segments;      segment_limit = segments + outline->num_vsegments;    }  }  static void  ah_outline_compute_edges( AH_Outline*  outline )  {    AH_Edge*      edges;    AH_Segment*   segments;    AH_Segment*   segment_limit;    AH_Direction  up_dir;    FT_Int*       p_num_edges;    FT_Int        dimension;    FT_Fixed      scale;    FT_Pos        edge_distance_threshold;    edges         = outline->horz_edges;    segments      = outline->horz_segments;    segment_limit = segments + outline->num_hsegments;    p_num_edges   = &outline->num_hedges;    up_dir        = ah_dir_right;    scale         = outline->y_scale;    for ( dimension = 1; dimension >= 0; dimension-- )    {      AH_Edge*     edge;      AH_Edge*     edge_limit;  /* really == edge + num_edges */      AH_Segment*  seg;      /*********************************************************************/      /*                                                                   */      /* We will begin by generating a sorted table of edges for the       */      /* current direction.  To do so, we simply scan each segment and try */      /* to find an edge in our table that corresponds to its position.    */      /*                                                                   */      /* If no edge is found, we create and insert a new edge in the       */      /* sorted table.  Otherwise, we simply add the segment to the edge's */      /* list which will be processed in the second step to compute the    */      /* edge's properties.                                                */      /*                                                                   */      /* Note that the edges table is sorted along the segment/edge        */      /* position.                                                         */      /*                                                                   */      /*********************************************************************/      edge_distance_threshold = FT_MulFix( outline->edge_distance_threshold,                                           scale );      if ( edge_distance_threshold > 64 / 4 )        edge_distance_threshold = 64 / 4;      edge_limit = edges;      for ( seg = segments; seg < segment_limit; seg++ )      {        AH_Edge*  found = 0;        /* look for an edge corresponding to the segment */        for ( edge = edges; edge < edge_limit; edge++ )        {          FT_Pos  dist;          dist = seg->pos - edge->fpos;          if ( dist < 0 )            dist = -dist;          dist = FT_MulFix( dist, scale );          if ( dist < edge_distance_threshold )          {            found = edge;            break;          }        }        if ( !found )        {          /* insert a new edge in the list and */          /* sort according to the position    */          while ( edge > edges && edge[-1].fpos > seg->pos )          {            edge[0] = edge[-1];            edge--;          }          edge_limit++;          /* clear all edge fields */          FT_MEM_SET( edge, 0, sizeof ( *edge ) );          /* add the segment to the new edge's list */          edge->first    = seg;          edge->last     = seg;          edge->fpos     = seg->pos;          edge->opos     = edge->pos = FT_MulFix( seg->pos, scale );          seg->edge_next = seg;        }        else        {          /* if an edge was found, simply add the segment to the edge's */          /* list                                                       */          seg->edge_next        = edge->first;          edge->last->edge_next = seg;          edge->last            = seg;        }      }      *p_num_edges = (FT_Int)( edge_limit - edges );      /*********************************************************************/      /*                                                                   */      /* Good, we will now compute each edge's properties according to     */      /* segments found on its position.  Basically, these are:            */      /*                                                                   */      /*  - edge's main direction                                          */      /*  - stem edge, serif edge or both (which defaults to stem then)    */      /*  - rounded edge, straigth or both (which defaults to straight)    */      /*  - link for edge                                                  */      /*                                                                   */      /*********************************************************************/      /* first of all, set the `edge' field in each segment -- this is */      /* required in order to compute edge links                       */      for ( edge = edges; edge < edge_limit; edge++ )      {        seg = edge->first;        if ( seg )          do          {            seg->edge = edge;            seg       = seg->edge_next;          }          while ( seg != edge->first );      }      /* now, compute each edge properties */      for ( edge = edges; edge < edge_limit; edge++ )      {        int  is_round    = 0;  /* does it contain round segments?    */        int  is_straight = 0;  /* does it contain straight segments? */        int  ups         = 0;  /* number of upwards segments         */        int  downs       = 0;  /* number of downwards segments       */        seg = edge->first;        do        {          FT_Bool  is_serif;          /* check for roundness of segment */          if ( seg->flags & ah_edge_round )            is_round++;          else            is_straight++;          /* check for segment direction */          if ( seg->dir == up_dir )            ups   += seg->max_coord-seg->min_coord;          else            downs += seg->max_coord-seg->min_coord;          /* check for links -- if seg->serif is set, then seg->link must */          /* be ignored                                                   */          is_serif = (FT_Bool)( seg->serif && seg->serif->edge != edge );          if ( seg->link || is_serif )          {            AH_Edge*     edge2;            AH_Segment*  seg2;            edge2 = edge->link;            seg2  = seg->link;            if ( is_serif )            {              seg2  = seg->serif;              edge2 = edge->serif;            }            if ( edge2 )            {              FT_Pos  edge_delta;              FT_Pos  seg_delta;              edge_delta = edge->fpos - edge2->fpos;              if ( edge_delta < 0 )                edge_delta = -edge_delta;              seg_delta = seg->pos - seg2->pos;              if ( seg_delta < 0 )                seg_delta = -seg_delta;              if ( seg_delta < edge_delta )                edge2 = seg2->edge;            }            else              edge2 = seg2->edge;            if ( is_serif )              edge->serif = edge2;            else              edge->link  = edge2;          }          seg = seg->edge_next;        } while ( seg != edge->first );        /* set the round/straight flags */        edge->flags = ah_edge_normal;        if ( is_round > 0 && is_round >= is_straight )          edge->flags |= ah_edge_round;        /* set the edge's main direction */        edge->dir = ah_dir_none;        if ( ups > downs )          edge->dir = up_dir;        else if ( ups < downs )          edge->dir = - up_dir;        else if ( ups == downs )          edge->dir = 0;  /* both up and down !! */        /* gets rid of serifs if link is set                */        /* XXX: This gets rid of many unpleasant artefacts! */        /*      Example: the `c' in cour.pfa at size 13     */        if ( edge->serif && edge->link )          edge->serif = 0;      }      edges         = outline->vert_edges;      segments      = outline->vert_segments;      segment_limit = segments + outline->num_vsegments;      p_num_edges   = &outline->num_vedges;      up_dir        = ah_dir_up;      scale         = outline->x_scale;    }  }  /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ah_outline_detect_features                                         */  /*                                                                       */  /* <Description>                                                         */  /*    Performs feature detection on a given AH_Outline object.           */  /*                                                                       */  FT_LOCAL_DEF( void )  ah_outline_detect_features( AH_Outline*  outline )  {    ah_outline_compute_segments( outline );    ah_outline_link_segments   ( outline );    ah_outline_compute_edges   ( outline );  }  /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ah_outline_compute_blue_edges                                      */  /*                                                                       */  /* <Description>                                                         */  /*    Computes the `blue edges' in a given outline (i.e. those that must */  /*    be snapped to a blue zone edge (top or bottom).                    */  /*                                                                       */  FT_LOCAL_DEF( void )  ah_outline_compute_blue_edges( AH_Outline*       outline,                                 AH_Face_Globals*  face_globals )  {    AH_Edge*     edge       = outline->horz_edges;    AH_Edge*     edge_limit = edge + outline->num_hedges;    AH_Globals*  globals    = &face_globals->design;    FT_Fixed     y_scale    = outline->y_scale;    FT_Bool      blue_active[ah_blue_max];    /* compute which blue zones are active, i.e. have their scaled */    /* size < 3/4 pixels                                           */    {      AH_Blue  blue;      FT_Bool  check = 0;      for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )      {        FT_Pos  ref, shoot, dist;        ref   = globals->blue_refs[blue];        shoot = globals->blue_shoots[blue];        dist  = ref-shoot;        if ( dist < 0 )          dist = -dist;        blue_active[blue] = 0;        if ( FT_MulFix( dist, y_scale ) < 48 )        {          blue_active[blue] = 1;          check = 1;        }      }      /* return immediately if no blue zone is active */      if ( !check )        return;    }    /* compute for each horizontal edge, which blue zone is closer */    for ( ; edge < edge_limit; edge++ )    {      AH_Blue  blue;      FT_Pos*  best_blue = 0;      FT_Pos   best_dist;  /* initial threshold */      /* compute the initial threshold as a fraction of the EM size */      best_dist = FT_MulFix( face_globals->face->units_per_EM / 40, y_scale );      if ( best_dist > 64 / 4 )        best_dist = 64 / 4;      for ( blue = ah_blue_capital_top; blue < ah_blue_max; blue++ )      {        /* if it is a top zone, check for right edges -- if it is a bottom */        /* zone, check for left edges                                      */        /*                                                                 */        /* of course, that's for TrueType XXX                              */        FT_Bool  is_top_blue  =                   FT_BOOL( AH_IS_TOP_BLUE( blue ) );        FT_Bool  is_major_dir =                   FT_BOOL( edge->dir == outline->horz_major_dir );        if ( !blue_active[blue] )          continue;        /* if it is a top zone, the edge must be against the major    */        /* direction; if it is a bottom zone, it must be in the major */        /* direction                                                  */        if ( is_top_blue ^ is_major_dir )        {          FT_Pos   dist;          FT_Pos*  blue_pos = globals->blue_refs + blue;          /* first of all, compare it to the reference position */          dist = edge->fpos - *blue_pos;          if ( dist < 0 )            dist = -dist;          dist = FT_MulFix( dist, y_scale );          if ( dist < best_dist )          {            best_dist = dist;            best_blue = blue_pos;          }          /* now, compare it to the overshoot position if the edge is     */          /* rounded, and if the edge is over the reference position of a */          /* top zone, or under the reference position of a bottom zone   */          if ( edge->flags & ah_edge_round && dist != 0 )          {            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < *blue_pos );            if ( is_top_blue ^ is_under_ref )            {              blue_pos = globals->blue_shoots + blue;              dist = edge->fpos - *blue_pos;              if ( dist < 0 )                dist = -dist;              dist = FT_MulFix( dist, y_scale );              if ( dist < best_dist )              {                best_dist = dist;                best_blue = blue_pos;              }            }          }        }      }      if ( best_blue )        edge->blue_edge = best_blue;    }  }  /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    ah_outline_scale_blue_edges                                        */  /*                                                                       */  /* <Description>                                                         */  /*    This functions must be called before hinting in order to re-adjust */  /*    the contents of the detected edges (basically change the `blue     */  /*    edge' pointer from `design units' to `scaled ones').               */  /*                                                                       */  FT_LOCAL_DEF( void )  ah_outline_scale_blue_edges( AH_Outline*       outline,                               AH_Face_Globals*  globals )  {    AH_Edge*  edge       = outline->horz_edges;    AH_Edge*  edge_limit = edge + outline->num_hedges;    FT_Int    delta;    delta = globals->scaled.blue_refs - globals->design.blue_refs;    for ( ; edge < edge_limit; edge++ )    {      if ( edge->blue_edge )        edge->blue_edge += delta;    }  }/* END */

⌨️ 快捷键说明

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