adding path stroker component (first steps)
This commit is contained in:
parent
318f3befc6
commit
b7e18efcd2
|
@ -0,0 +1,144 @@
|
||||||
|
#ifndef __FT_STROKER_H__
|
||||||
|
#define __FT_STROKER_H__
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_OUTLINE_H
|
||||||
|
|
||||||
|
FT_BEGIN_HEADER
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
*
|
||||||
|
* @type: FT_Stroker
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
* opaque handler to a path stroker object
|
||||||
|
*/
|
||||||
|
typedef struct FT_StrokerRec_* FT_Stroker;
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
*
|
||||||
|
* @enum: FT_Stroker_LineJoin
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
* these values determine how two joining lines are rendered
|
||||||
|
* in a stroker.
|
||||||
|
*
|
||||||
|
* @values:
|
||||||
|
* FT_STROKER_LINEJOIN_ROUND ::
|
||||||
|
* used to render rounded line joins. circular arcs are used
|
||||||
|
* to join two lines smoothly
|
||||||
|
*
|
||||||
|
* FT_STROKER_LINEJOIN_BEVEL ::
|
||||||
|
* used to render beveled line joins; i.e. the two joining lines
|
||||||
|
* are extended until they intersect
|
||||||
|
*
|
||||||
|
* FT_STROKER_LINEJOIN_MITER ::
|
||||||
|
* same as beveled rendering, except that an additional line
|
||||||
|
* break is added if the angle between the two joining lines
|
||||||
|
* is too closed (this is useful to avoid unpleasant spikes
|
||||||
|
* in beveled rendering).
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FT_STROKER_LINEJOIN_ROUND = 0,
|
||||||
|
FT_STROKER_LINEJOIN_BEVEL,
|
||||||
|
FT_STROKER_LINEJOIN_MITER
|
||||||
|
|
||||||
|
} FT_Stroker_LineJoin;
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************
|
||||||
|
*
|
||||||
|
* @enum: FT_Stroker_LineCap
|
||||||
|
*
|
||||||
|
* @description:
|
||||||
|
* these values determine how the end of opened sub-paths are
|
||||||
|
* rendered in a stroke
|
||||||
|
*
|
||||||
|
* @values:
|
||||||
|
* FT_STROKER_LINECAP_BUTT ::
|
||||||
|
* the end of lines is rendered as a full stop on the last
|
||||||
|
* point itself
|
||||||
|
*
|
||||||
|
* FT_STROKER_LINECAP_ROUND ::
|
||||||
|
* the end of lines is rendered as a half-circle around the
|
||||||
|
* last point
|
||||||
|
*
|
||||||
|
* FT_STROKER_LINEJOIN_MITER ::
|
||||||
|
* the end of lines is rendered as a square around the
|
||||||
|
* last point
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FT_STROKER_LINECAP_BUTT = 0,
|
||||||
|
FT_STROKER_LINECAP_ROUND,
|
||||||
|
FT_STROKER_LINECAP_SQUARE
|
||||||
|
|
||||||
|
} FT_Stroker_LineCap;
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_New( FT_Memory memory,
|
||||||
|
FT_Stroker *astroker );
|
||||||
|
|
||||||
|
FT_EXPORT( void )
|
||||||
|
FT_Stroker_Set( FT_Stroker stroker,
|
||||||
|
FT_Fixed radius,
|
||||||
|
FT_Stroker_LineCap line_cap,
|
||||||
|
FT_Stroker_LineJoin line_join,
|
||||||
|
FT_Fixed miter_limit );
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_BeginSubPath( FT_Stroker stroker,
|
||||||
|
FT_Pos x,
|
||||||
|
FT_Pos y,
|
||||||
|
FT_Bool open );
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_EndSubPath( FT_Stroker stroker );
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_LineTo( FT_Stroker stroker,
|
||||||
|
FT_Pos to_x,
|
||||||
|
FT_Pos to_y );
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_ConicTo( FT_Stroker stroker,
|
||||||
|
FT_Pos control_x,
|
||||||
|
FT_Pos control_y,
|
||||||
|
FT_Pos to_x,
|
||||||
|
FT_Pos to_y );
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_CubicTo( FT_Stroker stroker,
|
||||||
|
FT_Pos control1_x,
|
||||||
|
FT_Pos control1_y,
|
||||||
|
FT_Pos control2_x,
|
||||||
|
FT_Pos control2_y,
|
||||||
|
FT_Pos to_x,
|
||||||
|
FT_Pos to_y );
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_GetCounts( FT_Stroker stroker,
|
||||||
|
FT_UInt *anum_points,
|
||||||
|
FT_UInt *anum_contours );
|
||||||
|
|
||||||
|
FT_EXPORT( void )
|
||||||
|
FT_Stroker_Export( FT_Stroker stroker,
|
||||||
|
FT_Outliner* outline );
|
||||||
|
|
||||||
|
FT_EXPORT( void )
|
||||||
|
FT_Stroker_Done( FT_Stroker stroker );
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT( FT_Error )
|
||||||
|
FT_Stroker_ParseOutline( FT_Stroker stroker,
|
||||||
|
FT_Outline* outline,
|
||||||
|
FT_Bool opened );
|
||||||
|
|
||||||
|
FT_END_HEADER
|
||||||
|
|
||||||
|
#endif /* __FT_STROKER_H__ */
|
|
@ -173,6 +173,27 @@ FT_BEGIN_HEADER
|
||||||
FT_Fixed y );
|
FT_Fixed y );
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* @function: */
|
||||||
|
/* FT_Angle_Diff */
|
||||||
|
/* */
|
||||||
|
/* @description: */
|
||||||
|
/* Returns the difference between two angles. The result is always */
|
||||||
|
/* constrained to the ]-PI..PI] interval */
|
||||||
|
/* */
|
||||||
|
/* @input: */
|
||||||
|
/* angle1 :: first angle */
|
||||||
|
/* angle2 :: second angle */
|
||||||
|
/* */
|
||||||
|
/* @return: */
|
||||||
|
/* contrainted value of 'value2-value1' */
|
||||||
|
/* */
|
||||||
|
FT_EXPORT_DEF( FT_Angle )
|
||||||
|
FT_Angle_Dif( FT_Angle angle1,
|
||||||
|
FT_Angle angle2 );
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* @function: */
|
/* @function: */
|
||||||
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_STROKER_H
|
||||||
|
#include FT_TRIGONOMETRY_H
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/***************************************************************************/
|
||||||
|
/***** *****/
|
||||||
|
/***** STROKE BORDERS *****/
|
||||||
|
/***** *****/
|
||||||
|
/***************************************************************************/
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FT_STROKE_TAG_ON = 1, /* on-curve point */
|
||||||
|
FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */
|
||||||
|
FT_STROKE_TAG_BEGIN = 4, /* sub-path start */
|
||||||
|
FT_STROKE_TAG_END = 8 /* sub-path end */
|
||||||
|
|
||||||
|
} FT_StrokeTags;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct FT_StrokeBorderRec_
|
||||||
|
{
|
||||||
|
FT_UInt num_points;
|
||||||
|
FT_UInt max_points;
|
||||||
|
FT_Vector* points;
|
||||||
|
FT_Byte* tags;
|
||||||
|
FT_Bool movable;
|
||||||
|
FT_Int start; /* index of current sub-path start point */
|
||||||
|
FT_Memory memory;
|
||||||
|
|
||||||
|
} FT_StrokeBorderRec, *FT_StrokeBorder;
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Error
|
||||||
|
ft_stroke_border_grow( FT_StrokeBorder border,
|
||||||
|
FT_UInt new_points )
|
||||||
|
{
|
||||||
|
FT_UInt old_max = border->max_points;
|
||||||
|
FT_UInt new_max = border->num_points + new_points;
|
||||||
|
FT_Error error = 0;
|
||||||
|
|
||||||
|
if ( new_max > old_max )
|
||||||
|
{
|
||||||
|
FT_UInt cur_max = old_max;
|
||||||
|
FT_Memory memory =
|
||||||
|
|
||||||
|
while ( cur_max < new_max )
|
||||||
|
cur_max += (cur_max >> 1) + 16;
|
||||||
|
|
||||||
|
if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||
|
||||||
|
FT_RENEW_ARRAY( border->tags, old_max, cur_max ) )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
|
border->max_points = cur_max;
|
||||||
|
}
|
||||||
|
Exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ft_stroke_border_close( FT_StrokeBorder border )
|
||||||
|
{
|
||||||
|
FT_ASSERT( border->start >= 0 );
|
||||||
|
|
||||||
|
border->tags[ border->start ] |= FT_STROKE_TAG_BEGIN;
|
||||||
|
border->tags[ border->num_points-1 ] |= FT_STROKE_TAG_END;
|
||||||
|
|
||||||
|
border->start = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Error
|
||||||
|
ft_stroke_border_lineto( FT_StrokeBorder border,
|
||||||
|
FT_Vector* to )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
FT_ASSERT( border->start >= 0 );
|
||||||
|
|
||||||
|
error = ft_stroker_border_grow( border, 1 );
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
FT_Vector* vec = border->points + border->num_points;
|
||||||
|
FT_Byte* tag = border->tags + border->num_points;
|
||||||
|
|
||||||
|
vec[0] = *to;
|
||||||
|
tag[0] = FT_STROKE_TAG_ON;
|
||||||
|
|
||||||
|
border->num_points += 1;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Error
|
||||||
|
ft_stroke_border_conicto( FT_StrokeBorder border,
|
||||||
|
FT_Vector* control,
|
||||||
|
FT_Vector* to )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
FT_ASSERT( border->start >= 0 );
|
||||||
|
|
||||||
|
error = ft_stroker_border_grow( border, 2 );
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
FT_Vector* vec = border->points + border->num_points;
|
||||||
|
FT_Byte* tag = border->tags + border->num_points;
|
||||||
|
|
||||||
|
vec[0] = *control;
|
||||||
|
vec[1] = *to;
|
||||||
|
|
||||||
|
tag[0] = 0;
|
||||||
|
tag[1] = FT_STROKE_TAG_ON;
|
||||||
|
|
||||||
|
border->num_points += 2;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Error
|
||||||
|
ft_stroke_border_cubicto( FT_StrokeBorder border,
|
||||||
|
FT_Vector* control1,
|
||||||
|
FT_Vector* control2,
|
||||||
|
FT_Vector* to )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
FT_ASSERT( border->start >= 0 );
|
||||||
|
|
||||||
|
error = ft_stroker_border_grow( border, 3 );
|
||||||
|
if (!error)
|
||||||
|
{
|
||||||
|
FT_Vector* vec = border->points + border->num_points;
|
||||||
|
FT_Byte* tag = border->tags + border->num_points;
|
||||||
|
|
||||||
|
vec[0] = *control1;
|
||||||
|
vec[1] = *control2;
|
||||||
|
vec[2] = *to;
|
||||||
|
|
||||||
|
tag[0] = FT_STROKE_TAG_CUBIC;
|
||||||
|
tag[1] = FT_STROKE_TAG_CUBIC;
|
||||||
|
tag[2] = FT_STROKE_TAG_ON;
|
||||||
|
|
||||||
|
border->num_points += 3;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FT_Error
|
||||||
|
ft_stroke_border_moveto( FT_StrokeBorder border,
|
||||||
|
FT_Vector* to )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
|
||||||
|
/* close current open path if any ? */
|
||||||
|
if ( border->start >= 0 )
|
||||||
|
ft_stroke_border_close( border );
|
||||||
|
|
||||||
|
border->start = border->num_points;
|
||||||
|
|
||||||
|
return ft_stroke_border_lineto( border, to );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ft_stroke_border_init( FT_StrokeBorder border,
|
||||||
|
FT_Memory memory )
|
||||||
|
{
|
||||||
|
border->memory = memory;
|
||||||
|
border->points = NULL;
|
||||||
|
border->tags = NULL;
|
||||||
|
|
||||||
|
border->num_points = 0;
|
||||||
|
border->max_points = 0;
|
||||||
|
border->start = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ft_stroke_border_reset( FT_StrokeBorder border )
|
||||||
|
{
|
||||||
|
border->num_points = 0;
|
||||||
|
border->start = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ft_stroke_border_done( FT_StrokeBorder border )
|
||||||
|
{
|
||||||
|
memory = border->memory;
|
||||||
|
|
||||||
|
FT_FREE( border->points );
|
||||||
|
FT_FREE( border->tags );
|
||||||
|
|
||||||
|
border->num_points = 0;
|
||||||
|
border->max_points = 0;
|
||||||
|
border->start = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
/***************************************************************************/
|
||||||
|
/***** *****/
|
||||||
|
/***** STROKER *****/
|
||||||
|
/***** *****/
|
||||||
|
/***************************************************************************/
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
#define FT_SIDE_TO_ROTATE(s) (FT_PI2 - (s)*FT_PI)
|
||||||
|
|
||||||
|
typedef struct FT_StrokerRec_
|
||||||
|
{
|
||||||
|
FT_Angle angle_in;
|
||||||
|
FT_Angle angle_out;
|
||||||
|
FT_Vector center;
|
||||||
|
FT_Bool first_point;
|
||||||
|
FT_Bool subpath_open;
|
||||||
|
FT_Angle subpath_angle;
|
||||||
|
FT_Vector subpath_start;
|
||||||
|
|
||||||
|
FT_Stroker_LineCap line_cap;
|
||||||
|
FT_Stroker_LineJoin line_join;
|
||||||
|
FT_Fixed miter_limit;
|
||||||
|
FT_Fixed radius;
|
||||||
|
|
||||||
|
FT_StrokeBorderRec borders[2];
|
||||||
|
FT_Memory memory;
|
||||||
|
|
||||||
|
} FT_StrokerRec;
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT_DEF( FT_Error )
|
||||||
|
FT_Stroker_New( FT_Memory memory,
|
||||||
|
FT_Stroker *astroker )
|
||||||
|
{
|
||||||
|
FT_Error error;
|
||||||
|
FT_Stroker stroker;
|
||||||
|
|
||||||
|
if ( !FT_NEW( stroker ) )
|
||||||
|
{
|
||||||
|
stroker->memory = memory;
|
||||||
|
|
||||||
|
ft_stroke_border_init( &stroker->borders[0], memory );
|
||||||
|
ft_stroke_border_init( &stroker->borders[1], memory );
|
||||||
|
}
|
||||||
|
*astroker = stroker;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_EXPORT_DEF( void )
|
||||||
|
FT_Stroker_Set( FT_Stroker stroker,
|
||||||
|
FT_Fixed radius,
|
||||||
|
FT_Stroker_LineCap line_cap,
|
||||||
|
FT_Stroker_LineJoin line_join,
|
||||||
|
FT_Fixed miter_limit )
|
||||||
|
{
|
||||||
|
stroker->radius = radius;
|
||||||
|
stroker->line_cap = line_cap;
|
||||||
|
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_EXPORT( void )
|
||||||
|
FT_Stroker_Done( FT_Stroker stroker )
|
||||||
|
{
|
||||||
|
if ( stroker )
|
||||||
|
{
|
||||||
|
FT_Memory memory = stroker->memory;
|
||||||
|
|
||||||
|
ft_stroke_border_done( &stroker->borders[0] );
|
||||||
|
ft_stroke_border_done( &stroker->borders[1] );
|
||||||
|
|
||||||
|
stroker->memory = NULL;
|
||||||
|
FT_FREE( stroker );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -451,4 +451,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* documentation is in fttrigon.h */
|
||||||
|
|
||||||
|
FT_EXPORT_DEF( FT_Angle )
|
||||||
|
FT_Angle_Dif( FT_Angle angle1,
|
||||||
|
FT_Angle angle2 )
|
||||||
|
{
|
||||||
|
FT_Angle delta = angle2 - angle1;
|
||||||
|
|
||||||
|
delta %= FT_ANGLE_2PI;
|
||||||
|
|
||||||
|
if ( delta > FT_ANGLE_PI )
|
||||||
|
delta -= FT_ANGLE_2PI;
|
||||||
|
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
|
Loading…
Reference in New Issue