📄 ahhint.c
字号:
edge1->pos = blue[0]; edge1->flags |= AH_EDGE_DONE; if ( edge2 && !edge2->blue_edge ) { ah_align_linked_edge( hinter, edge1, edge2, dimension ); edge2->flags |= AH_EDGE_DONE; } if ( !anchor ) anchor = edge; } } /* now we will align all stem edges, trying to maintain the */ /* relative order of stems in the glyph */ for ( edge = edges; edge < edge_limit; edge++ ) { AH_EdgeRec* edge2; if ( edge->flags & AH_EDGE_DONE ) continue; /* skip all non-stem edges */ edge2 = edge->link; if ( !edge2 ) { has_serifs++; continue; } /* now align the stem */ /* this should not happen, but it's better to be safe */ if ( edge2->blue_edge || edge2 < edge ) { ah_align_linked_edge( hinter, edge2, edge, dimension ); edge->flags |= AH_EDGE_DONE; continue; } if ( !anchor ) {#ifdef FT_CONFIG_CHESTER_STEM FT_Pos org_len, org_center, cur_len; FT_Pos cur_pos1, error1, error2, u_off, d_off; org_len = edge2->opos - edge->opos; cur_len = ah_compute_stem_width( hinter, dimension, org_len, edge->flags, edge2->flags ); if ( cur_len <= 64 ) u_off = d_off = 32; else { u_off = 38; d_off = 26; } if ( cur_len < 96 ) { org_center = edge->opos + ( org_len >> 1 ); cur_pos1 = ( org_center + 32 ) & -64; error1 = org_center - ( cur_pos1 - u_off ); if ( error1 < 0 ) error1 = -error1; error2 = org_center - ( cur_pos1 + d_off ); if ( error2 < 0 ) error2 = -error2; if ( error1 < error2 ) cur_pos1 -= u_off; else cur_pos1 += d_off; edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; } else edge->pos = ( edge->opos + 32 ) & -64; anchor = edge; edge->flags |= AH_EDGE_DONE; ah_align_linked_edge( hinter, edge, edge2, dimension );#else /* !FT_CONFIG_CHESTER_STEM */ edge->pos = ( edge->opos + 32 ) & -64; anchor = edge; edge->flags |= AH_EDGE_DONE; ah_align_linked_edge( hinter, edge, edge2, dimension );#endif /* !FT_CONFIG_CHESTER_STEM */ } else { FT_Pos org_pos, org_len, org_center, cur_len; FT_Pos cur_pos1, cur_pos2, delta1, delta2; org_pos = anchor->pos + ( edge->opos - anchor->opos ); org_len = edge2->opos - edge->opos; org_center = org_pos + ( org_len >> 1 );#ifdef FT_CONFIG_CHESTER_SERIF cur_len = ah_compute_stem_width( hinter, dimension, org_len, edge->flags, edge2->flags );#else /* !FT_CONFIG_CHESTER_SERIF */ cur_len = ah_compute_stem_width( hinter, dimension, org_len );#endif /* !FT_CONFIG_CHESTER_SERIF */#ifdef FT_CONFIG_CHESTER_STEM if ( cur_len < 96 ) { FT_Pos u_off, d_off; cur_pos1 = ( org_center + 32 ) & -64; if (cur_len <= 64 ) u_off = d_off = 32; else { u_off = 38; d_off = 26; } delta1 = org_center - ( cur_pos1 - u_off ); if ( delta1 < 0 ) delta1 = -delta1; delta2 = org_center - ( cur_pos1 + d_off ); if ( delta2 < 0 ) delta2 = -delta2; if ( delta1 < delta2 ) cur_pos1 -= u_off; else cur_pos1 += d_off; edge->pos = cur_pos1 - cur_len / 2; edge2->pos = cur_pos1 + cur_len / 2; } else { org_pos = anchor->pos + ( edge->opos - anchor->opos ); org_len = edge2->opos - edge->opos; org_center = org_pos + ( org_len >> 1 ); cur_len = ah_compute_stem_width( hinter, dimension, org_len, edge->flags, edge2->flags ); cur_pos1 = ( org_pos + 32 ) & -64; delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center ); if ( delta1 < 0 ) delta1 = -delta1; cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - cur_len; delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center ); if ( delta2 < 0 ) delta2 = -delta2; edge->pos = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2; edge2->pos = edge->pos + cur_len; }#else /* !FT_CONFIG_CHESTER_STEM */ cur_pos1 = ( org_pos + 32 ) & -64; delta1 = ( cur_pos1 + ( cur_len >> 1 ) - org_center ); if ( delta1 < 0 ) delta1 = -delta1; cur_pos2 = ( ( org_pos + org_len + 32 ) & -64 ) - cur_len; delta2 = ( cur_pos2 + ( cur_len >> 1 ) - org_center ); if ( delta2 < 0 ) delta2 = -delta2; edge->pos = ( delta1 <= delta2 ) ? cur_pos1 : cur_pos2; edge2->pos = edge->pos + cur_len;#endif /* !FT_CONFIG_CHESTER_STEM */ edge->flags |= AH_EDGE_DONE; edge2->flags |= AH_EDGE_DONE; if ( edge > edges && edge->pos < edge[-1].pos ) edge->pos = edge[-1].pos; } } /* make sure that lowercase m's maintain their symmetry */ /* In general, lowercase m's have six vertical edges if they are sans */ /* serif, or twelve if they are avec serif. This implementation is */ /* based on that assumption, and seems to work very well with most */ /* faces. However, if for a certain face this assumption is not */ /* true, the m is just rendered like before. In addition, any stem */ /* correction will only be applied to symmetrical glyphs (even if the */ /* glyph is not an m), so the potential for unwanted distortion is */ /* relatively low. */ /* We don't handle horizontal edges since we can't easily assure that */ /* the third (lowest) stem aligns with the base line; it might end up */ /* one pixel higher or lower. */ n_edges = edge_limit - edges; if ( !dimension && ( n_edges == 6 || n_edges == 12 ) ) { AH_EdgeRec *edge1, *edge2, *edge3; FT_Pos dist1, dist2, span, delta; if ( n_edges == 6 ) { edge1 = edges; edge2 = edges + 2; edge3 = edges + 4; } else { edge1 = edges + 1; edge2 = edges + 5; edge3 = edges + 9; } dist1 = edge2->opos - edge1->opos; dist2 = edge3->opos - edge2->opos; span = dist1 - dist2; if ( span < 0 ) span = -span; if ( span < 8 ) { delta = edge3->pos - ( 2 * edge2->pos - edge1->pos ); edge3->pos -= delta; if ( edge3->link ) edge3->link->pos -= delta; /* move the serifs along with the stem */ if ( n_edges == 12 ) { ( edges + 8 )->pos -= delta; ( edges + 11 )->pos -= delta; } edge3->flags |= AH_EDGE_DONE; if ( edge3->link ) edge3->link->flags |= AH_EDGE_DONE; } } if ( !has_serifs ) goto Next_Dimension; /* now hint the remaining edges (serifs and single) in order */ /* to complete our processing */ for ( edge = edges; edge < edge_limit; edge++ ) { if ( edge->flags & AH_EDGE_DONE ) continue; if ( edge->serif ) ah_align_serif_edge( hinter, edge->serif, edge, dimension ); else if ( !anchor ) { edge->pos = ( edge->opos + 32 ) & -64; anchor = edge; } else edge->pos = anchor->pos + ( ( edge->opos-anchor->opos + 32 ) & -64 ); edge->flags |= AH_EDGE_DONE; if ( edge > edges && edge->pos < edge[-1].pos ) edge->pos = edge[-1].pos; if ( edge + 1 < edge_limit && edge[1].flags & AH_EDGE_DONE && edge->pos > edge[1].pos ) edge->pos = edge[1].pos; } Next_Dimension: edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; } } /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /**** ****/ /**** P O I N T H I N T I N G ****/ /**** ****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ static void ah_hinter_align_edge_points( AH_Hinter hinter ) { AH_Outline outline = hinter->glyph; AH_Edge edges; AH_Edge edge_limit; FT_Int dimension; edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Edge edge; edge = edges; for ( ; edge < edge_limit; edge++ ) { /* move the points of each segment */ /* in each edge to the edge's position */ AH_Segment seg = edge->first; do { AH_Point point = seg->first; for (;;) { if ( dimension ) { point->y = edge->pos; point->flags |= AH_FLAG_TOUCH_Y; } else { point->x = edge->pos; point->flags |= AH_FLAG_TOUCH_X; } if ( point == seg->last ) break; point = point->next; } seg = seg->edge_next; } while ( seg != edge->first ); } edges = outline->vert_edges; edge_limit = edges + outline->num_vedges; } } /* hint the strong points -- this is equivalent to the TrueType `IP' */ /* hinting instruction */ static void ah_hinter_align_strong_points( AH_Hinter hinter ) { AH_Outline outline = hinter->glyph; FT_Int dimension; AH_Edge edges; AH_Edge edge_limit; AH_Point points; AH_Point point_limit; AH_Flags touch_flag; points = outline->points; point_limit = points + outline->num_points; edges = outline->horz_edges; edge_limit = edges + outline->num_hedges; touch_flag = AH_FLAG_TOUCH_Y; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Point point; AH_Edge edge; if ( edges < edge_limit ) for ( point = points; point < point_limit; point++ ) { FT_Pos u, ou, fu; /* point position */ FT_Pos delta; if ( point->flags & touch_flag ) continue;#ifndef AH_OPTION_NO_WEAK_INTERPOLATION /* if this point is candidate to weak interpolation, we will */ /* interpolate it after all strong points have been processed */ if ( ( point->flags & AH_FLAG_WEAK_INTERPOLATION ) && !( point->flags & AH_FLAG_INFLECTION ) ) continue;#endif if ( dimension ) { u = point->fy; ou = point->oy; } else { u = point->fx; ou = point->ox; } fu = u; /* is the point before the first edge? */ edge = edges; delta = edge->fpos - u; if ( delta >= 0 ) { u = edge->pos - ( edge->opos - ou ); goto Store_Point; } /* is the point after the last edge? */ edge = edge_limit - 1; delta = u - edge->fpos; if ( delta >= 0 ) { u = edge->pos + ( ou - edge->opos ); goto Store_Point; }#if 1 { FT_UInt min, max, mid; FT_Pos fpos; /* find enclosing edges */ min = 0; max = edge_limit - edges; while ( min < max ) { mid = ( max + min ) >> 1; edge = edges + mid; fpos = edge->fpos; if ( u < fpos ) max = mid; else if ( u > fpos ) min = mid + 1; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -