📄 ftstroke.c
字号:
goto Exit; } /* process the corner */ stroker->angle_out = stroker->subpath_angle; turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ); /* no specific corner processing is required if the turn is 0 */ if ( turn != 0 ) { /* when we turn to the right, the inside side is 0 */ inside_side = 0; /* otherwise, the inside side is 1 */ if ( turn < 0 ) inside_side = 1; error = ft_stroker_inside( stroker, inside_side ); if ( error ) goto Exit; /* process the outside side */ error = ft_stroker_outside( stroker, 1 - inside_side ); if ( error ) goto Exit; } /* then end our two subpaths */ ft_stroke_border_close( stroker->borders + 0, 1 ); ft_stroke_border_close( stroker->borders + 1, 0 ); } Exit: return error; } /* documentation is in ftstroke.h */ FT_EXPORT_DEF( FT_Error ) FT_Stroker_GetBorderCounts( FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours ) { FT_UInt num_points = 0, num_contours = 0; FT_Error error; if ( !stroker || border > 1 ) { error = FT_Err_Invalid_Argument; goto Exit; } error = ft_stroke_border_get_counts( stroker->borders + border, &num_points, &num_contours ); Exit: if ( anum_points ) *anum_points = num_points; if ( anum_contours ) *anum_contours = num_contours; return error; } /* documentation is in ftstroke.h */ FT_EXPORT_DEF( FT_Error ) FT_Stroker_GetCounts( FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours ) { FT_UInt count1, count2, num_points = 0; FT_UInt count3, count4, num_contours = 0; FT_Error error; error = ft_stroke_border_get_counts( stroker->borders + 0, &count1, &count2 ); if ( error ) goto Exit; error = ft_stroke_border_get_counts( stroker->borders + 1, &count3, &count4 ); if ( error ) goto Exit; num_points = count1 + count3; num_contours = count2 + count4; Exit: *anum_points = num_points; *anum_contours = num_contours; return error; } /* documentation is in ftstroke.h */ FT_EXPORT_DEF( void ) FT_Stroker_ExportBorder( FT_Stroker stroker, FT_StrokerBorder border, FT_Outline* outline ) { if ( border == FT_STROKER_BORDER_LEFT || border == FT_STROKER_BORDER_RIGHT ) { FT_StrokeBorder sborder = & stroker->borders[border]; if ( sborder->valid ) ft_stroke_border_export( sborder, outline ); } } /* documentation is in ftstroke.h */ FT_EXPORT_DEF( void ) FT_Stroker_Export( FT_Stroker stroker, FT_Outline* outline ) { FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_LEFT, outline ); FT_Stroker_ExportBorder( stroker, FT_STROKER_BORDER_RIGHT, outline ); } /* documentation is in ftstroke.h */ /* * The following is very similar to FT_Outline_Decompose, except * that we do support opened paths, and do not scale the outline. */ FT_EXPORT_DEF( FT_Error ) FT_Stroker_ParseOutline( FT_Stroker stroker, FT_Outline* outline, FT_Bool opened ) { FT_Vector v_last; FT_Vector v_control; FT_Vector v_start; FT_Vector* point; FT_Vector* limit; char* tags; FT_Error error; FT_Int n; /* index of contour in outline */ FT_UInt first; /* index of first point in contour */ FT_Int tag; /* current point's state */ if ( !outline || !stroker ) return FT_Err_Invalid_Argument; FT_Stroker_Rewind( stroker ); first = 0; for ( n = 0; n < outline->n_contours; n++ ) { FT_UInt last; /* index of last point in contour */ last = outline->contours[n]; limit = outline->points + last; /* skip empty points; we don't stroke these */ if ( last <= first ) { first = last + 1; continue; } v_start = outline->points[first]; v_last = outline->points[last]; v_control = v_start; point = outline->points + first; tags = outline->tags + first; tag = FT_CURVE_TAG( tags[0] ); /* A contour cannot start with a cubic control point! */ if ( tag == FT_CURVE_TAG_CUBIC ) goto Invalid_Outline; /* check first point to determine origin */ if ( tag == FT_CURVE_TAG_CONIC ) { /* First point is conic control. Yes, this happens. */ if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON ) { /* start at last point if it is on the curve */ v_start = v_last; limit--; } else { /* if both first and last points are conic, */ /* start at their middle and record its position */ /* for closure */ v_start.x = ( v_start.x + v_last.x ) / 2; v_start.y = ( v_start.y + v_last.y ) / 2; v_last = v_start; } point--; tags--; } error = FT_Stroker_BeginSubPath( stroker, &v_start, opened ); if ( error ) goto Exit; while ( point < limit ) { point++; tags++; tag = FT_CURVE_TAG( tags[0] ); switch ( tag ) { case FT_CURVE_TAG_ON: /* emit a single line_to */ { FT_Vector vec; vec.x = point->x; vec.y = point->y; error = FT_Stroker_LineTo( stroker, &vec ); if ( error ) goto Exit; continue; } case FT_CURVE_TAG_CONIC: /* consume conic arcs */ v_control.x = point->x; v_control.y = point->y; Do_Conic: if ( point < limit ) { FT_Vector vec; FT_Vector v_middle; point++; tags++; tag = FT_CURVE_TAG( tags[0] ); vec = point[0]; if ( tag == FT_CURVE_TAG_ON ) { error = FT_Stroker_ConicTo( stroker, &v_control, &vec ); if ( error ) goto Exit; continue; } if ( tag != FT_CURVE_TAG_CONIC ) goto Invalid_Outline; v_middle.x = ( v_control.x + vec.x ) / 2; v_middle.y = ( v_control.y + vec.y ) / 2; error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle ); if ( error ) goto Exit; v_control = vec; goto Do_Conic; } error = FT_Stroker_ConicTo( stroker, &v_control, &v_start ); goto Close; default: /* FT_CURVE_TAG_CUBIC */ { FT_Vector vec1, vec2; if ( point + 1 > limit || FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC ) goto Invalid_Outline; point += 2; tags += 2; vec1 = point[-2]; vec2 = point[-1]; if ( point <= limit ) { FT_Vector vec; vec = point[0]; error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec ); if ( error ) goto Exit; continue; } error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start ); goto Close; } } } Close: if ( error ) goto Exit; error = FT_Stroker_EndSubPath( stroker ); if ( error ) goto Exit; first = last + 1; } return 0; Exit: return error; Invalid_Outline: return FT_Err_Invalid_Outline; } extern const FT_Glyph_Class ft_outline_glyph_class; /* documentation is in ftstroke.h */ FT_EXPORT_DEF( FT_Error ) FT_Glyph_Stroke( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy ) { FT_Error error = FT_Err_Invalid_Argument; FT_Glyph glyph = NULL; if ( pglyph == NULL ) goto Exit; glyph = *pglyph; if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class ) goto Exit; { FT_Glyph copy; error = FT_Glyph_Copy( glyph, © ); if ( error ) goto Exit; glyph = copy; } { FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; FT_Outline* outline = &oglyph->outline; FT_UInt num_points, num_contours; error = FT_Stroker_ParseOutline( stroker, outline, 0 ); if ( error ) goto Fail; (void)FT_Stroker_GetCounts( stroker, &num_points, &num_contours ); FT_Outline_Done( glyph->library, outline ); error = FT_Outline_New( glyph->library, num_points, num_contours, outline ); if ( error ) goto Fail; outline->n_points = 0; outline->n_contours = 0; FT_Stroker_Export( stroker, outline ); } if ( destroy ) FT_Done_Glyph( *pglyph ); *pglyph = glyph; goto Exit; Fail: FT_Done_Glyph( glyph ); glyph = NULL; if ( !destroy ) *pglyph = NULL; Exit: return error; } /* documentation is in ftstroke.h */ FT_EXPORT_DEF( FT_Error ) FT_Glyph_StrokeBorder( FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy ) { FT_Error error = FT_Err_Invalid_Argument; FT_Glyph glyph = NULL; if ( pglyph == NULL ) goto Exit; glyph = *pglyph; if ( glyph == NULL || glyph->clazz != &ft_outline_glyph_class ) goto Exit; { FT_Glyph copy; error = FT_Glyph_Copy( glyph, © ); if ( error ) goto Exit; glyph = copy; } { FT_OutlineGlyph oglyph = (FT_OutlineGlyph) glyph; FT_StrokerBorder border; FT_Outline* outline = &oglyph->outline; FT_UInt num_points, num_contours; border = FT_Outline_GetOutsideBorder( outline ); if ( inside ) { if ( border == FT_STROKER_BORDER_LEFT ) border = FT_STROKER_BORDER_RIGHT; else border = FT_STROKER_BORDER_LEFT; } error = FT_Stroker_ParseOutline( stroker, outline, 0 ); if ( error ) goto Fail; (void)FT_Stroker_GetBorderCounts( stroker, border, &num_points, &num_contours ); FT_Outline_Done( glyph->library, outline ); error = FT_Outline_New( glyph->library, num_points, num_contours, outline ); if ( error ) goto Fail; outline->n_points = 0; outline->n_contours = 0; FT_Stroker_ExportBorder( stroker, border, outline ); } if ( destroy ) FT_Done_Glyph( *pglyph ); *pglyph = glyph; goto Exit; Fail: FT_Done_Glyph( glyph ); glyph = NULL; if ( !destroy ) *pglyph = NULL; Exit: return error; }/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -