📄 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 + -