📄 ahglyph.c
字号:
point->oy = point->y = FT_MulFix( vec->y, y_scale ); point->flags = 0; } } /* compute Bezier flags */ { char* tag = source->tags; for ( point = points; point < point_limit; point++, tag++ ) { switch ( FT_CURVE_TAG( *tag ) ) { case FT_Curve_Tag_Conic: point->flags = ah_flag_conic; break; case FT_Curve_Tag_Cubic: point->flags = ah_flag_cubic; break; default: ; } } } /* compute `next' and `prev' */ { FT_Int contour_index; AH_Point* prev; AH_Point* first; AH_Point* end; contour_index = 0; first = points; end = points + source->contours[0]; prev = end; for ( point = points; point < point_limit; point++ ) { point->prev = prev; if ( point < end ) { point->next = point + 1; prev = point; } else { point->next = first; contour_index++; if ( point + 1 < point_limit ) { end = points + source->contours[contour_index]; first = point + 1; prev = end; } } } } /* set-up the contours array */ { AH_Point** contour = outline->contours; AH_Point** contour_limit = contour + outline->num_contours; short* end = source->contours; short idx = 0; for ( ; contour < contour_limit; contour++, end++ ) { contour[0] = points + idx; idx = (short)( end[0] + 1 ); } } /* compute directions of in & out vectors */ { for ( point = points; point < point_limit; point++ ) { AH_Point* prev; AH_Point* next; FT_Vector ivec, ovec; prev = point->prev; ivec.x = point->fx - prev->fx; ivec.y = point->fy - prev->fy; point->in_dir = ah_compute_direction( ivec.x, ivec.y ); next = point->next; ovec.x = next->fx - point->fx; ovec.y = next->fy - point->fy; point->out_dir = ah_compute_direction( ovec.x, ovec.y );#ifndef AH_OPTION_NO_WEAK_INTERPOLATION if ( point->flags & (ah_flag_conic | ah_flag_cubic) ) { Is_Weak_Point: point->flags |= ah_flag_weak_interpolation; } else if ( point->out_dir == point->in_dir ) { AH_Angle angle_in, angle_out, delta; if ( point->out_dir != ah_dir_none ) goto Is_Weak_Point; angle_in = ah_angle( &ivec ); angle_out = ah_angle( &ovec ); delta = angle_in - angle_out; if ( delta > AH_PI ) delta = AH_2PI - delta; if ( delta < 0 ) delta = -delta; if ( delta < 2 ) goto Is_Weak_Point; } else if ( point->in_dir == -point->out_dir ) goto Is_Weak_Point;#endif } } } Exit: return error; } FT_LOCAL_DEF( void ) ah_setup_uv( AH_Outline* outline, AH_UV source ) { AH_Point* point = outline->points; AH_Point* point_limit = point + outline->num_points; for ( ; point < point_limit; point++ ) { FT_Pos u, v; switch ( source ) { case ah_uv_fxy: u = point->fx; v = point->fy; break; case ah_uv_fyx: u = point->fy; v = point->fx; break; case ah_uv_oxy: u = point->ox; v = point->oy; break; case ah_uv_oyx: u = point->oy; v = point->ox; break; case ah_uv_yx: u = point->y; v = point->x; break; case ah_uv_ox: u = point->x; v = point->ox; break; case ah_uv_oy: u = point->y; v = point->oy; break; default: u = point->x; v = point->y; break; } point->u = u; point->v = v; } } FT_LOCAL_DEF( void ) ah_outline_compute_segments( AH_Outline* outline ) { int dimension; AH_Segment* segments; FT_Int* p_num_segments; AH_Direction segment_dir; AH_Direction major_dir; segments = outline->horz_segments; p_num_segments = &outline->num_hsegments; major_dir = ah_dir_right; /* This value must be positive! */ segment_dir = major_dir; /* set up (u,v) in each point */ ah_setup_uv( outline, ah_uv_fyx ); for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Point** contour = outline->contours; AH_Point** contour_limit = contour + outline->num_contours; AH_Segment* segment = segments; FT_Int num_segments = 0;#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_MEM_SET( segment, 0, sizeof ( *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; 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_MEM_SET( segment, 0, sizeof ( *segment ) ); segment->dir = segment_dir; segment->flags = ah_edge_normal; segment->first = min_point; segment->last = min_point; segment->pos = min_pos; num_segments++; segment++; } /* insert maximum segment */ if ( max_point ) { /* clear all segment fields */ FT_MEM_SET( segment, 0, sizeof ( *segment ) ); segment->dir = segment_dir; segment->flags = ah_edge_normal; segment->first = max_point; segment->last = max_point; segment->pos = max_pos; 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; int dimension; ah_setup_uv( outline, ah_uv_fyx ); segments = outline->horz_segments; segment_limit = segments + outline->num_hsegments; for ( dimension = 1; dimension >= 0; dimension-- ) { AH_Segment* seg1; AH_Segment* seg2; /* 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; {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -