* src/base/ftstroke.c, include/freetype/ftstroke.h: fixing bugs and
adding FT_Glyph_Stroke and FT_Glyph_StrokerBorder APIs
This commit is contained in:
parent
4d9b4128f9
commit
cda62fca98
@ -21,6 +21,7 @@
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
FT_BEGIN_HEADER
|
||||
|
||||
@ -128,7 +129,7 @@ FT_BEGIN_HEADER
|
||||
{
|
||||
FT_STROKER_BORDER_LEFT = 0,
|
||||
FT_STROKER_BORDER_RIGHT
|
||||
|
||||
|
||||
} FT_StrokerBorder;
|
||||
|
||||
|
||||
@ -173,7 +174,7 @@ FT_BEGIN_HEADER
|
||||
FT_EXPORT( FT_StrokerBorder )
|
||||
FT_Outline_GetOutsideBorder( FT_Outline* outline );
|
||||
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function:
|
||||
@ -234,6 +235,24 @@ FT_BEGIN_HEADER
|
||||
FT_Fixed miter_limit );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_Stroker_Rewind
|
||||
*
|
||||
* @description:
|
||||
* Reset a stroker object without changing its attributes.
|
||||
* you should call this function before beginning a new
|
||||
* series of calls to @FT_Stroker_BeginSubPath/@FT_Stroker_EndSubPath
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
*/
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_Rewind( FT_Stroker stroker );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function:
|
||||
@ -264,6 +283,8 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
* If `opened' is 1, the outline is processed as an open path, and the
|
||||
* stroker will generate a single `stroke' outline.
|
||||
*
|
||||
* this function calls @FT_Stroker_Rewind automatically
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Stroker_ParseOutline( FT_Stroker stroker,
|
||||
@ -278,7 +299,7 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
* @description:
|
||||
* Start a new sub-path in the stroker.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -309,7 +330,7 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
* @description:
|
||||
* Close the current sub-path in the stroker.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -334,7 +355,7 @@ FT_BEGIN_HEADER
|
||||
* @description:
|
||||
* `Draw' a single line segment in the stroker's current sub-path,
|
||||
* from the last position.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -362,7 +383,7 @@ FT_BEGIN_HEADER
|
||||
* @description:
|
||||
* `Draw; a single quadratic bezier in the stroker's current sub-path,
|
||||
* from the last position.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -394,7 +415,7 @@ FT_BEGIN_HEADER
|
||||
* @description:
|
||||
* `Draw' a single cubic Bézier in the stroker's current sub-path,
|
||||
* from the last position.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -432,7 +453,7 @@ FT_BEGIN_HEADER
|
||||
* with the stroker. It will return the number of points and
|
||||
* contours necessary to export one of the `border' or `stroke'
|
||||
* outlines generated by the stroker.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -453,7 +474,7 @@ FT_BEGIN_HEADER
|
||||
* @note:
|
||||
* When an outline, or a sub-path, is `closed', the stroker generates
|
||||
* two independent `border' outlines, named `left' and `right'.
|
||||
*
|
||||
*
|
||||
* When the outline, or a sub-path, is `opened', the stroker merges
|
||||
* the `border' outlines with caps. The `left' border receives all
|
||||
* points, while the `right' border becomes empty.
|
||||
@ -477,7 +498,7 @@ FT_BEGIN_HEADER
|
||||
* Call this function after @FT_Stroker_GetBorderCounts to
|
||||
* export the corresponding border to your own @FT_Outline
|
||||
* structure.
|
||||
*
|
||||
*
|
||||
* Note that this function will append the border points and
|
||||
* contours to your outline, but will not try to resize its
|
||||
* arrays.
|
||||
@ -499,7 +520,7 @@ FT_BEGIN_HEADER
|
||||
*
|
||||
* When an outline, or a sub-path, is `closed', the stroker generates
|
||||
* two independent `border' outlines, named `left' and `right'
|
||||
*
|
||||
*
|
||||
* When the outline, or a sub-path, is `opened', the stroker merges
|
||||
* the `border' outlines with caps. The `left' border receives all
|
||||
* points, while the `right' border becomes empty.
|
||||
@ -523,7 +544,7 @@ FT_BEGIN_HEADER
|
||||
* with the stroker. It returns the number of points and
|
||||
* contours necessary to export all points/borders from the stroked
|
||||
* outline/path.
|
||||
*
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* The target stroker handle.
|
||||
@ -552,7 +573,7 @@ FT_BEGIN_HEADER
|
||||
* @description:
|
||||
* Call this function after @FT_Stroker_GetBorderCounts to
|
||||
* export the all borders to your own @FT_Outline structure.
|
||||
*
|
||||
*
|
||||
* Note that this function will append the border points and
|
||||
* contours to your outline, but will not try to resize its
|
||||
* arrays.
|
||||
@ -584,6 +605,73 @@ FT_BEGIN_HEADER
|
||||
FT_EXPORT( void )
|
||||
FT_Stroker_Done( FT_Stroker stroker );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_Glyph_Stroke
|
||||
*
|
||||
* @description:
|
||||
* stroke a given outline glyph object with a given stroker
|
||||
*
|
||||
* @inout:
|
||||
* pglyph :: source glyph handle on input, new glyph handle
|
||||
* on output.
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* A stroker handle.
|
||||
*
|
||||
* destroy :: boolean. If TRUE, the source glyph object is destroyed
|
||||
* on success
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* the source glyph is untouched in case of error.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Glyph_Stroke( FT_Glyph *pglyph,
|
||||
FT_Stroker stroker,
|
||||
FT_Bool destroy );
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* @function:
|
||||
* FT_Glyph_StrokeBorder
|
||||
*
|
||||
* @description:
|
||||
* stroke a given outline glyph object with a given stroker, but
|
||||
* only returns either its inside or outside border
|
||||
*
|
||||
* @inout:
|
||||
* pglyph :: source glyph handle on input, new glyph handle
|
||||
* on output.
|
||||
*
|
||||
* @input:
|
||||
* stroker ::
|
||||
* A stroker handle.
|
||||
*
|
||||
* inside :: boolean. If TRUE, return the inside border; otherwise,
|
||||
* the outside border
|
||||
*
|
||||
* destroy :: boolean. If TRUE, the source glyph object is destroyed
|
||||
* on success
|
||||
*
|
||||
* @return:
|
||||
* FreeType error code. 0 means success
|
||||
*
|
||||
* @note:
|
||||
* the source glyph is untouched in case of error.
|
||||
*/
|
||||
FT_EXPORT( FT_Error )
|
||||
FT_Glyph_StrokeBorder( FT_Glyph *pglyph,
|
||||
FT_Stroker stroker,
|
||||
FT_Bool inside,
|
||||
FT_Bool destroy );
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_INTERNAL_MEMORY_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
#include FT_INTERNAL_OBJECTS_H
|
||||
|
||||
FT_EXPORT_DEF( FT_StrokerBorder )
|
||||
FT_Outline_GetInsideBorder( FT_Outline* outline )
|
||||
@ -41,8 +41,8 @@
|
||||
FT_Orientation o = FT_Outline_Get_Orientation( outline );
|
||||
|
||||
|
||||
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT
|
||||
: FT_STROKER_BORDER_LEFT ;
|
||||
return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT
|
||||
: FT_STROKER_BORDER_RIGHT ;
|
||||
}
|
||||
|
||||
|
||||
@ -581,7 +581,8 @@
|
||||
{
|
||||
/* copy point locations */
|
||||
FT_ARRAY_COPY( outline->points + outline->n_points,
|
||||
border->points, border->num_points );
|
||||
border->points,
|
||||
border->num_points );
|
||||
|
||||
/* copy tags */
|
||||
{
|
||||
@ -689,8 +690,18 @@
|
||||
stroker->line_join = line_join;
|
||||
stroker->miter_limit = miter_limit;
|
||||
|
||||
ft_stroke_border_reset( &stroker->borders[0] );
|
||||
ft_stroke_border_reset( &stroker->borders[1] );
|
||||
FT_Stroker_Rewind( stroker );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( void )
|
||||
FT_Stroker_Rewind( FT_Stroker stroker )
|
||||
{
|
||||
if ( stroker )
|
||||
{
|
||||
ft_stroke_border_reset( &stroker->borders[0] );
|
||||
ft_stroke_border_reset( &stroker->borders[1] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1373,7 +1384,6 @@
|
||||
{
|
||||
FT_Error error = 0;
|
||||
|
||||
|
||||
if ( stroker->subpath_open )
|
||||
{
|
||||
FT_StrokeBorder right = stroker->borders;
|
||||
@ -1406,6 +1416,15 @@
|
||||
FT_Angle turn;
|
||||
FT_Int inside_side;
|
||||
|
||||
/* close the path if needed
|
||||
*/
|
||||
if ( stroker->center.x != stroker->subpath_start.x ||
|
||||
stroker->center.y != stroker->subpath_start.y )
|
||||
{
|
||||
error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* process the corner */
|
||||
stroker->angle_out = stroker->subpath_angle;
|
||||
@ -1434,14 +1453,9 @@
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* we will first end our two subpaths */
|
||||
/* then end our two subpaths */
|
||||
ft_stroke_border_close( stroker->borders + 0 );
|
||||
ft_stroke_border_close( stroker->borders + 1 );
|
||||
|
||||
/* now, add the reversed left subpath to "right" */
|
||||
error = ft_stroker_add_reverse_left( stroker, 0 );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
@ -1561,6 +1575,8 @@
|
||||
if ( !outline || !stroker )
|
||||
return FT_Err_Invalid_Argument;
|
||||
|
||||
FT_Stroker_Rewind( stroker );
|
||||
|
||||
first = 0;
|
||||
|
||||
for ( n = 0; n < outline->n_contours; n++ )
|
||||
@ -1731,4 +1747,150 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern const FT_Glyph_Class ft_outline_glyph_class;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
border = 1-border;
|
||||
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user