ref: fa0346d6d98d98c61042810b5bd6223606e0f3ca
parent: cd9f3b3b5a89fe6ee32e605212eb921544392448
author: David Turner <[email protected]>
date: Fri Jan 16 03:57:05 EST 2004
* src/base/ftstroke.c, include/freetype/ftstroke.h: fixing bugs and adding FT_Glyph_Stroke and FT_Glyph_StrokerBorder APIs
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -21,6 +21,7 @@
#include <ft2build.h>
#include FT_OUTLINE_H
+#include FT_GLYPH_H
FT_BEGIN_HEADER
@@ -128,7 +129,7 @@
{
FT_STROKER_BORDER_LEFT = 0,
FT_STROKER_BORDER_RIGHT
-
+
} FT_StrokerBorder;
@@ -173,7 +174,7 @@
FT_EXPORT( FT_StrokerBorder )
FT_Outline_GetOutsideBorder( FT_Outline* outline );
-
+
/**************************************************************
*
* @function:
@@ -237,6 +238,24 @@
/**************************************************************
*
* @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:
* FT_Stroker_ParseOutline
*
* @description:
@@ -264,6 +283,8 @@
*
* 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 @@
*
* @description:
* Start a new sub-path in the stroker.
- *
+ *
* @input:
* stroker ::
* The target stroker handle.
@@ -309,7 +330,7 @@
*
* @description:
* Close the current sub-path in the stroker.
- *
+ *
* @input:
* stroker ::
* The target stroker handle.
@@ -334,7 +355,7 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* @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 @@
* 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 @@
*
* 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 @@
* 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 @@
* @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.
@@ -583,6 +604,73 @@
*/
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 );
/* */
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -22,8 +22,8 @@
#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,12 +690,22 @@
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] );
+ }
+ }
+
+
+ FT_EXPORT_DEF( void )
FT_Stroker_Done( FT_Stroker stroker )
{
if ( stroker )
@@ -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++ )
@@ -1729,6 +1745,152 @@
Invalid_Outline:
return FT_Err_Invalid_Outline;
}
+
+
+
+ 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 */