📄 ahglyph.c
字号:
#ifdef AH_HINT_METRICS AH_Point min_point = 0; AH_Point max_point = 0; FT_Pos min_coord = 32000; FT_Pos max_coord = -32000;#endif /* do each contour separately */ for ( ; contour < contour_limit; contour++ ) { AH_Point point = contour[0]; AH_Point last = point->prev; int on_edge = 0; FT_Pos min_pos = 32000; /* minimum segment pos != min_coord */ FT_Pos max_pos = -32000; /* maximum segment pos != max_coord */ FT_Bool passed;#ifdef AH_HINT_METRICS if ( point->u < min_coord ) { min_coord = point->u; min_point = point; } if ( point->u > max_coord ) { max_coord = point->u; max_point = point; }#endif if ( point == last ) /* skip singletons -- just in case */ continue; if ( ABS( last->out_dir ) == major_dir && ABS( point->out_dir ) == major_dir ) { /* we are already on an edge, try to locate its start */ last = point; for (;;) { point = point->prev; if ( ABS( point->out_dir ) != major_dir ) { point = point->next; break; } if ( point == last ) break; } } last = point; passed = 0; for (;;) { FT_Pos u, v; if ( on_edge ) { u = point->u; if ( u < min_pos ) min_pos = u; if ( u > max_pos ) max_pos = u; if ( point->out_dir != segment_dir || point == last ) { /* we are just leaving an edge; record a new segment! */ segment->last = point; segment->pos = ( min_pos + max_pos ) >> 1; /* a segment is round if either its first or last point */ /* is a control point */ if ( ( segment->first->flags | point->flags ) & AH_FLAG_CONTROL ) segment->flags |= AH_EDGE_ROUND; /* compute segment size */ min_pos = max_pos = point->v; v = segment->first->v; if ( v < min_pos ) min_pos = v; if ( v > max_pos ) max_pos = v; segment->min_coord = min_pos; segment->max_coord = max_pos; on_edge = 0; num_segments++; segment++; /* fallthrough */ } } /* now exit if we are at the start/end point */ if ( point == last ) { if ( passed ) break; passed = 1; } if ( !on_edge && ABS( point->out_dir ) == major_dir ) { /* this is the start of a new segment! */ segment_dir = point->out_dir; /* clear all segment fields */ FT_ZERO( segment ); segment->dir = segment_dir; segment->flags = AH_EDGE_NORMAL; min_pos = max_pos = point->u; segment->first = point; segment->last = point; segment->contour = contour; segment->score = 32000; segment->link = NULL; on_edge = 1;#ifdef AH_HINT_METRICS if ( point == max_point ) max_point = 0; if ( point == min_point ) min_point = 0;#endif } point = point->next; } } /* contours */#ifdef AH_HINT_METRICS /* we need to ensure that there are edges on the left-most and */ /* right-most points of the glyph in order to hint the metrics; */ /* we do this by inserting fake segments when needed */ if ( dimension == 0 ) { AH_Point point = outline->points; AH_Point point_limit = point + outline->num_points; FT_Pos min_pos = 32000; FT_Pos max_pos = -32000; min_point = 0; max_point = 0; /* compute minimum and maximum points */ for ( ; point < point_limit; point++ ) { FT_Pos x = point->fx; if ( x < min_pos ) { min_pos = x; min_point = point; } if ( x > max_pos ) { max_pos = x; max_point = point; } } /* insert minimum segment */ if ( min_point ) { /* clear all segment fields */ FT_ZERO( segment ); segment->dir = segment_dir; segment->flags = AH_EDGE_NORMAL; segment->first = min_point; segment->last = min_point; segment->pos = min_pos; segment->score = 32000; segment->link = NULL; num_segments++; segment++; } /* insert maximum segment */ if ( max_point ) { /* clear all segment fields */ FT_ZERO( segment ); segment->dir = segment_dir; segment->flags = AH_EDGE_NORMAL; segment->first = max_point; segment->last = max_point; segment->pos = max_pos; segment->score = 32000; segment->link = NULL; num_segments++; segment++; } }#endif /* AH_HINT_METRICS */ *p_num_segments = num_segments; segments = outline->vert_segments; major_dir = AH_DIR_UP; p_num_segments = &outline->num_vsegments; ah_setup_uv( outline, AH_UV_FXY ); } } FT_LOCAL_DEF( void ) ah_outline_link_segments( AH_Outline outline ) { AH_Segment segments; AH_Segment segment_limit; AH_Direction major_dir; int dimension; segments = outline->horz_segments; segment_limit = segments + outline->num_hsegments; major_dir = outline->horz_major_dir; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Segment seg1; AH_Segment seg2;#if 0 /* now compare each segment to the others */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) { FT_Pos best_score; AH_Segment best_segment; /* the fake segments are introduced to hint the metrics -- */ /* we must never link them to anything */ if ( seg1->first == seg1->last ) continue; best_segment = seg1->link; if ( best_segment ) best_score = seg1->score; else best_score = +32000; for ( seg2 = segments; seg2 < segment_limit; seg2++ ) if ( seg1 != seg2 && seg1->dir + seg2->dir == 0 ) { FT_Pos pos1 = seg1->pos; FT_Pos pos2 = seg2->pos; FT_Bool is_dir; FT_Bool is_pos; /* check that the segments are correctly oriented and */ /* positioned to form a black distance */ is_dir = (FT_Bool)( seg1->dir == outline->horz_major_dir || seg1->dir == outline->vert_major_dir ); is_pos = (FT_Bool)( pos1 > pos2 ); if ( pos1 == pos2 || !(is_dir ^ is_pos) ) continue; { 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; if ( len >= 8 ) { dist = seg2->pos - seg1->pos; if ( dist < 0 ) dist = -dist; score = dist + 3000 / 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++; } }#endif /* 0 */#if 1 /* the following code does the same, but much faster! */ /* now compare each segment to the others */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) { /* the fake segments are introduced to hint the metrics -- */ /* we must never link them to anything */ if ( seg1->first == seg1->last || seg1->dir != major_dir ) continue; for ( seg2 = segments; seg2 < segment_limit; seg2++ ) if ( seg2 != seg1 && seg1->dir + seg2->dir == 0 ) { FT_Pos pos1 = seg1->pos; FT_Pos pos2 = seg2->pos; FT_Pos dist = pos2 - pos1; if ( dist < 0 ) continue; { FT_Pos min = seg1->min_coord; FT_Pos max = seg1->max_coord; FT_Pos len, score; if ( min < seg2->min_coord ) min = seg2->min_coord; if ( max > seg2->max_coord ) max = seg2->max_coord; len = max - min; if ( len >= 8 ) { score = dist + 3000 / len; if ( score < seg1->score ) { seg1->score = score; seg1->link = seg2; } if ( score < seg2->score ) { seg2->score = score; seg2->link = seg1; } } } } }#endif /* 1 */ /* now, compute the `serif' segments */ for ( seg1 = segments; seg1 < segment_limit; seg1++ ) { seg2 = seg1->link; if ( seg2 ) { seg2->num_linked++; if ( seg2->link != seg1 ) { seg1->link = 0; seg1->serif = seg2->link; } } } segments = outline->vert_segments; segment_limit = segments + outline->num_vsegments; major_dir = outline->vert_major_dir; } } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -