From fa0346d6d98d98c61042810b5bd6223606e0f3ca Mon Sep 17 00:00:00 2001 From: David Turner Date: Fri, 16 Jan 2004 08:57:05 +0000 Subject: [PATCH] * src/base/ftstroke.c, include/freetype/ftstroke.h: fixing bugs and adding FT_Glyph_Stroke and FT_Glyph_StrokerBorder APIs --- include/freetype/ftstroke.h | 114 +++++++++++++++++++--- src/base/ftstroke.c | 188 +++++++++++++++++++++++++++++++++--- 2 files changed, 276 insertions(+), 26 deletions(-) diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h index 61315e678..9972c0ebc 100644 --- a/include/freetype/ftstroke.h +++ b/include/freetype/ftstroke.h @@ -21,6 +21,7 @@ #include #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 diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c index 63ff3a32b..198d9bfdb 100644 --- a/src/base/ftstroke.c +++ b/src/base/ftstroke.c @@ -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 */