⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 path2d_stroker.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
			}		}	}	outline->n_points = outline->n_points + border->num_points;} /***************************************************************************/ /***************************************************************************/ /*****                                                                 *****/ /*****                           STROKER                               *****/ /*****                                                                 *****/ /***************************************************************************/ /***************************************************************************/#define FT_SIDE_TO_ROTATE( s )   ( GF_PI2 - (s) * GF_PI )typedef struct  FT_StrokerRec_{	Fixed angle_in;	Fixed angle_out;	GF_Point2D            center;	Bool              first_point;	Fixed subpath_angle;	GF_Point2D            subpath_start;	u32 line_cap;	u32 line_join;	Fixed miter_limit;	Fixed radius;	Bool              valid;	Bool              closing;	FT_StrokeBorderRec   borders[2];} FT_StrokerRec, FT_Stroker;  /* creates a circular arc at a corner or cap */static s32 ft_stroker_arcto( FT_Stroker  *stroker, s32 side ){    Fixed total, rotate;    Fixed         radius = stroker->radius;    s32 error  = 0;    FT_StrokeBorder  border = stroker->borders + side;    rotate = FT_SIDE_TO_ROTATE( side );    total = gf_angle_diff( stroker->angle_in, stroker->angle_out);    if ( total == GF_PI ) total = -rotate * 2;    error = ft_stroke_border_arcto( border,                                    &stroker->center,                                    radius,                                    stroker->angle_in + rotate,                                    total );    border->movable = 0;    return error;}  /* adds a cap at the end of an opened path */static s32 ft_stroker_cap(FT_Stroker  *stroker, Fixed angle, s32 side){    s32 error  = 0;    if ( stroker->line_cap == GF_LINE_CAP_ROUND) {		/* OK we cheat a bit here compared to FT original code, and use a rough cubic cap instead of		a circle to deal with arbitrary orientation of regular paths where arc cap is not always properly oriented.		Rather than computing orientation we simply approximate to conic - btw this takes less memory than		exact circle cap since cubics are natively supported - we don't use conic since result is not so good looking*/		GF_Point2D delta, delta2, ctl1, ctl2, end;		Fixed rotate = FT_SIDE_TO_ROTATE( side );		Fixed radius = stroker->radius;		FT_StrokeBorder  border = stroker->borders + side;		delta = gf_v2d_from_polar(radius, angle);		delta.x = 4*delta.x/3;		delta.y = 4*delta.y/3;		delta2 = gf_v2d_from_polar(radius, angle + rotate);		ctl1.x = delta.x + stroker->center.x + delta2.x;		ctl1.y = delta.y + stroker->center.y + delta2.y;		delta2 = gf_v2d_from_polar(radius, angle - rotate);		ctl2.x = delta.x + delta2.x + stroker->center.x;		ctl2.y = delta.y + delta2.y + stroker->center.y;		end.x = delta2.x + stroker->center.x;		end.y = delta2.y + stroker->center.y;		error = ft_stroke_border_cubicto( border, &ctl1, &ctl2, &end);	} else if ( stroker->line_cap == GF_LINE_CAP_SQUARE) {		/* add a square cap */		GF_Point2D        delta, delta2;		Fixed rotate = FT_SIDE_TO_ROTATE( side );		Fixed radius = stroker->radius;		FT_StrokeBorder  border = stroker->borders + side;		delta2 = gf_v2d_from_polar(radius, angle + rotate);		delta = gf_v2d_from_polar(radius, angle);		delta.x += stroker->center.x + delta2.x;		delta.y += stroker->center.y + delta2.y;		error = ft_stroke_border_lineto( border, &delta, 0 );		if ( error )			goto Exit;		delta2 = gf_v2d_from_polar(radius, angle - rotate);		delta = gf_v2d_from_polar(radius, angle);		delta.x += delta2.x + stroker->center.x;		delta.y += delta2.y + stroker->center.y;		error = ft_stroke_border_lineto( border, &delta, 0 );    } else if ( stroker->line_cap == GF_LINE_CAP_TRIANGLE) {		/* add a triangle cap */		GF_Point2D delta;		Fixed radius = stroker->radius;		FT_StrokeBorder  border = stroker->borders + side;		border->movable = 0;		delta = gf_v2d_from_polar(radius, angle);		delta.x += stroker->center.x;		delta.y += stroker->center.y;		error = ft_stroke_border_lineto(border, &delta, 0);    }Exit:    return error;}/* process an inside corner, i.e. compute intersection */static s32 ft_stroker_inside(FT_Stroker *stroker, s32 side){	FT_StrokeBorder  border = stroker->borders + side;	Fixed phi, theta, rotate;	Fixed length, thcos, sigma;	GF_Point2D        delta;	s32 error = 0;	rotate = FT_SIDE_TO_ROTATE( side );	/* compute median angle */	theta = gf_angle_diff( stroker->angle_in, stroker->angle_out );	if ( theta == GF_PI )		theta = rotate;	else		theta = theta / 2;	phi = stroker->angle_in + theta;	thcos  = gf_cos( theta );	sigma  = gf_mulfix( stroker->miter_limit, thcos );	if ( sigma < FIX_ONE ) {		delta = gf_v2d_from_polar(stroker->radius, stroker->angle_out + rotate );		delta.x += stroker->center.x;		delta.y += stroker->center.y;		if (!stroker->closing) border->movable = 0;	} else {		length = gf_divfix( stroker->radius, thcos );		delta = gf_v2d_from_polar(length, phi + rotate );		delta.x += stroker->center.x;		delta.y += stroker->center.y;	}	error = ft_stroke_border_lineto( border, &delta, 0 );	return error;}	/* process an outside corner, i.e. compute bevel/miter/round */static s32 ft_stroker_outside( FT_Stroker *stroker, s32 side ){	FT_StrokeBorder  border = stroker->borders + side;	s32 error;	Fixed rotate;	u32 join = stroker->line_join;	if ( join == GF_LINE_JOIN_MITER_SVG ) {		Fixed sin_theta, inv_sin_theta;		join = GF_LINE_JOIN_MITER;		sin_theta = gf_sin(gf_angle_diff( stroker->angle_out - GF_PI, stroker->angle_in) / 2 );		if (sin_theta) {			inv_sin_theta = gf_invfix(sin_theta); 			if (inv_sin_theta > stroker->miter_limit) join = GF_LINE_JOIN_BEVEL;		} else {			join = GF_LINE_JOIN_BEVEL;		}	}	if ( join == GF_LINE_JOIN_ROUND ) {		error = ft_stroker_arcto( stroker, side );	} else if (join == GF_LINE_JOIN_BEVEL) {		GF_Point2D  delta;		rotate = FT_SIDE_TO_ROTATE( side );		delta = gf_v2d_from_polar(stroker->radius, stroker->angle_out + rotate );		delta.x += stroker->center.x;		delta.y += stroker->center.y;		/*prevent moving current point*/		border->movable = 0;		/*and add un-movable end point*/		error = ft_stroke_border_lineto( border, &delta, 0);	} else {		/* this is a mitered or beveled corner */		Fixed  sigma, radius = stroker->radius;		Fixed theta, phi;		Fixed thcos;		Bool  miter = 1;		rotate = FT_SIDE_TO_ROTATE( side );		theta  = gf_angle_diff( stroker->angle_in, stroker->angle_out );		if ( theta == GF_PI ) {			theta = rotate;			phi   = stroker->angle_in;		} else {			theta = theta / 2;			phi   = stroker->angle_in + theta + rotate;		}		thcos = gf_cos( theta );		sigma = gf_mulfix( stroker->miter_limit, thcos );		if ( sigma >= FIX_ONE ) {			miter = 0;		} 		/* this is a miter (broken angle) */		if ( miter ) {			GF_Point2D  middle, delta;			Fixed   length;			/* compute middle point */			middle = gf_v2d_from_polar(gf_mulfix(radius, stroker->miter_limit), phi);			middle.x += stroker->center.x;			middle.y += stroker->center.y;			/* compute first angle point */			length = gf_mulfix(radius, gf_divfix( FIX_ONE - sigma, ABS( gf_sin( theta ) ) ) );			delta = gf_v2d_from_polar(length, phi + rotate );			delta.x += middle.x;			delta.y += middle.y;			error = ft_stroke_border_lineto( border, &delta, 0 );			if ( error )				goto Exit;			/* compute second angle point */			delta = gf_v2d_from_polar(length, phi - rotate);			delta.x += middle.x;			delta.y += middle.y;			error = ft_stroke_border_lineto( border, &delta, 0 );			if ( error )				goto Exit;			/* finally, add a movable end point */			delta = gf_v2d_from_polar(radius, stroker->angle_out + rotate );			delta.x += stroker->center.x;			delta.y += stroker->center.y;			error = ft_stroke_border_lineto( border, &delta, 1);		}		/* this is a bevel (intersection) */		else {			Fixed   length;			GF_Point2D  delta;			length = gf_divfix( stroker->radius, thcos );			delta = gf_v2d_from_polar(length, phi );			delta.x += stroker->center.x;			delta.y += stroker->center.y;			error = ft_stroke_border_lineto( border, &delta, 0 );			if (error) goto Exit;			/* now add end point */			delta = gf_v2d_from_polar(stroker->radius, stroker->angle_out + rotate );			delta.x += stroker->center.x;			delta.y += stroker->center.y;			error = ft_stroke_border_lineto( border, &delta, 1 );		}	}Exit:	return error;}static s32 ft_stroker_process_corner(FT_Stroker *stroker ){	s32 error = 0;	Fixed turn;    s32 inside_side;	turn = gf_angle_diff( stroker->angle_in, stroker->angle_out );    /* no specific corner processing is required if the turn is 0 */    if ( turn == 0 )		goto Exit;    /* 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;    /* process the inside side */	error = ft_stroker_inside( stroker, inside_side );	if ( error ) goto Exit;    /* process the outside side */    error = ft_stroker_outside( stroker, 1 - inside_side );Exit:    return error;}  /* add two points to the left and right borders corresponding to the */  /* start of the subpath..                                            */static s32 ft_stroker_subpath_start( FT_Stroker *stroker, Fixed start_angle ){	GF_Point2D        delta;	GF_Point2D        point;	s32 error;	FT_StrokeBorder  border;		delta = gf_v2d_from_polar(stroker->radius, start_angle + GF_PI2 );    point.x = stroker->center.x + delta.x;    point.y = stroker->center.y + delta.y;    border = stroker->borders;    error = ft_stroke_border_moveto( border, &point );    if ( error )		goto Exit;    point.x = stroker->center.x - delta.x;    point.y = stroker->center.y - delta.y;    border++;    error = ft_stroke_border_moveto( border, &point );    /* save angle for last cap */    stroker->subpath_angle = start_angle;    stroker->first_point   = 0;Exit:    return error;}static s32 FT_Stroker_LineTo( FT_Stroker *stroker, GF_Point2D*  to, Bool is_last){	s32 error = 0;	FT_StrokeBorder  border;	GF_Point2D        delta;	Fixed angle;	s32 side;    delta.x = to->x - stroker->center.x;    delta.y = to->y - stroker->center.y;	if (!is_last && !delta.x && !delta.y) return 0;    angle = gf_atan2( delta.y, delta.x);    delta = gf_v2d_from_polar(stroker->radius, angle + GF_PI2 );    /* process corner if necessary */    if ( stroker->first_point ) {		/* This is the first segment of a subpath.  We need to     */		/* add a point to each border at their respective starting */		/* point locations.                                        */		error = ft_stroker_subpath_start( stroker, angle );		if ( error )			goto Exit;    } else {		/* process the current corner */		stroker->angle_out = angle;		error = ft_stroker_process_corner( stroker );		if ( error ) 			goto Exit;    }    /* now add a line segment to both the "inside" and "outside" paths */    for ( border = stroker->borders, side = 1; side >= 0; side--, border++ ) {		GF_Point2D  point;		point.x = to->x + delta.x;		point.y = to->y + delta.y;		error = ft_stroke_border_lineto( border, &point, 1 );		if ( error )			goto Exit;		delta.x = -delta.x;		delta.y = -delta.y;    }    stroker->angle_in = angle;    stroker->center   = *to;Exit:    return error;}static s32 FT_Stroker_ConicTo(FT_Stroker *stroker, GF_Point2D*  control, GF_Point2D * to){	s32 error = 0;    GF_Point2D   bez_stack[34];    GF_Point2D*  arc;    GF_Point2D*  limit = bez_stack + 30;    Fixed start_angle;    Bool first_arc = 1;    arc    = bez_stack;    arc[0] = *to;    arc[1] = *control;    arc[2] = stroker->center;    while ( arc >= bez_stack ) {		Fixed angle_in, angle_out;		angle_in = angle_out = 0;  /* remove compiler warnings */		if ( arc < limit                                             &&			!ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )		{			ft_conic_split( arc );			arc += 2;			continue;		}		if ( first_arc ) {			first_arc = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -