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

📄 path2d_stroker.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
			start_angle = angle_in;			/* process corner if necessary */			if ( stroker->first_point )				error = ft_stroker_subpath_start( stroker, start_angle );			else {				stroker->angle_out = start_angle;				error = ft_stroker_process_corner( stroker );			}		}		/* the arc's angle is small enough; we can add it directly to each */		/* border                                                          */		{        			GF_Point2D  ctrl, end;			Fixed theta, phi, rotate;			Fixed length;			s32 side;			theta  = gf_angle_diff( angle_in, angle_out ) / 2;			phi    = angle_in + theta;			length = gf_divfix( stroker->radius, gf_cos( theta ) );			for ( side = 0; side <= 1; side++ ) {				rotate = FT_SIDE_TO_ROTATE( side );				/* compute control point */				ctrl = gf_v2d_from_polar(length, phi + rotate );				ctrl.x += arc[1].x;				ctrl.y += arc[1].y;				/* compute end point */				end = gf_v2d_from_polar(stroker->radius, angle_out + rotate );				end.x += arc[0].x;				end.y += arc[0].y;				error = ft_stroke_border_conicto( stroker->borders + side, &ctrl, &end );				if ( error )					goto Exit;			}		}		arc -= 2;		if ( arc < bez_stack )			stroker->angle_in = angle_out;    }    stroker->center = *to;Exit:    return error;}static s32 FT_Stroker_CubicTo(FT_Stroker *stroker,                      GF_Point2D*  control1,                      GF_Point2D*  control2,                      GF_Point2D*  to ){    s32 error = 0;	GF_Point2D   bez_stack[37];    GF_Point2D*  arc;    GF_Point2D*  limit = bez_stack + 32;    Fixed start_angle;    Bool     first_arc = 1;    arc    = bez_stack;    arc[0] = *to;    arc[1] = *control2;    arc[2] = *control1;    arc[3] = stroker->center;    while ( arc >= bez_stack ) {		Fixed angle_in, angle_mid, angle_out;		/* remove compiler warnings */		angle_in = angle_out = angle_mid = 0;		if (arc < limit && 			!ft_cubic_is_small_enough( arc, &angle_in, &angle_mid, &angle_out ) )		{			ft_cubic_split( arc );			arc += 3;			continue;		}		if ( first_arc ) {			first_arc = 0;			/* process corner if necessary */			start_angle = angle_in;			if ( stroker->first_point )				error = ft_stroker_subpath_start( stroker, start_angle );			else {				stroker->angle_out = start_angle;				error = ft_stroker_process_corner( stroker );			}			if ( error )				goto Exit;		}		/* the arc's angle is small enough; we can add it directly to each */		/* border                                                          */		{			GF_Point2D  ctrl1, ctrl2, end;			Fixed theta1, phi1, theta2, phi2, rotate;			Fixed length1, length2;			s32 side;			theta1  = ABS( angle_mid - angle_in ) / 2;			theta2  = ABS( angle_out - angle_mid ) / 2;			phi1    = (angle_mid + angle_in ) / 2;			phi2    = (angle_mid + angle_out ) / 2;			length1 = gf_divfix( stroker->radius, gf_cos( theta1 ) );			length2 = gf_divfix( stroker->radius, gf_cos(theta2) );			for ( side = 0; side <= 1; side++ ) {				rotate = FT_SIDE_TO_ROTATE( side );				/* compute control points */				ctrl1 = gf_v2d_from_polar(length1, phi1 + rotate );				ctrl1.x += arc[2].x;				ctrl1.y += arc[2].y;				ctrl2 = gf_v2d_from_polar(length2, phi2 + rotate );				ctrl2.x += arc[1].x;				ctrl2.y += arc[1].y;				/* compute end point */				end = gf_v2d_from_polar(stroker->radius, angle_out + rotate );				end.x += arc[0].x;				end.y += arc[0].y;				error = ft_stroke_border_cubicto( stroker->borders + side,					&ctrl1, &ctrl2, &end );				if ( error )					goto Exit;			}		}		arc -= 3;		if ( arc < bez_stack )			stroker->angle_in = angle_out;    }    stroker->center = *to;Exit:    return error;}static s32 FT_Stroker_BeginSubPath(FT_Stroker *stroker, GF_Point2D*  to){    /* We cannot process the first point, because there is not enough      */    /* information regarding its corner/cap.  The latter will be processed */    /* in the "end_subpath" routine.                                       */    /*                                                                     */    stroker->first_point   = 1;    stroker->center        = *to;    /* record the subpath start point index for each border */    stroker->subpath_start = *to;    return 0;}static s32 ft_stroker_add_reverse_left( FT_Stroker *stroker, Bool     open ){    FT_StrokeBorder  right  = stroker->borders + 0;    FT_StrokeBorder  left   = stroker->borders + 1;    s32 new_points;    s32 error  = 0;	if (!left->num_points) return 0;    assert( left->start >= 0 );    new_points = left->num_points - left->start;    if ( new_points > 0 ) {		error = ft_stroke_border_grow( right, (u32)new_points );		if ( error )			goto Exit;		{			GF_Point2D*  dst_point = right->points + right->num_points;			u8*    dst_tag   = right->tags   + right->num_points;			GF_Point2D*  src_point = left->points  + left->num_points - 1;			u8*    src_tag   = left->tags    + left->num_points - 1;			while ( src_point >= left->points + left->start ) {				*dst_point = *src_point;				*dst_tag   = *src_tag;				if ( open )					dst_tag[0] &= ~( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END );				else { 					/* switch begin/end tags if necessary.. */					if ( dst_tag[0] & ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) )						dst_tag[0] ^= ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END );				}				src_point--;				src_tag--;				dst_point++;				dst_tag++;			}		}		left->num_points   = left->start;		right->num_points += new_points;		right->movable = 0;		left->movable  = 0;    }Exit:    return error;}/* there's a lot of magic in this function! */static s32 FT_Stroker_EndSubPath( FT_Stroker *stroker, Bool do_close){    s32  error  = 0;	FT_StrokeBorder  right = stroker->borders;	if (do_close) {		Fixed turn;		s32 inside_side;		/* process the corner */		stroker->angle_out = stroker->subpath_angle;		turn               = gf_angle_diff(stroker->angle_in, stroker->angle_out );		/* no specific corner processing is required if the turn is 0 */		if ( turn != 0 ) {			/* 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;			/* IMPORTANT: WE DO NOT PROCESS THE INSIDE BORDER HERE! */			/* 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 );			if ( error )				goto Exit;		}		ft_stroker_add_reverse_left(stroker, 0);		/* then end our two subpaths */		ft_stroke_border_close( stroker->borders + 0 );		ft_stroke_border_close( stroker->borders + 1 );	} else {		/* All right, this is an opened path, we need to add a cap between */		/* right & left, add the reverse of left, then add a final cap     */		/* between left & right.                                           */		error = ft_stroker_cap( stroker, stroker->angle_in, 0 );		if ( error ) goto Exit;		/* add reversed points from "left" to "right" */		error = ft_stroker_add_reverse_left( stroker, 1 );		if ( error ) goto Exit;		/* now add the final cap */		stroker->center = stroker->subpath_start;		error = ft_stroker_cap( stroker,			stroker->subpath_angle + GF_PI, 0 );		if ( error )			goto Exit;		/* Now end the right subpath accordingly.  The left one is */		/* rewind and doesn't need further processing.             */		ft_stroke_border_close( right );	}Exit:	return error;}static s32 FT_Stroker_GetCounts( FT_Stroker *stroker, u32 *anum_points, u32 *anum_contours ){    u32 count1, count2, num_points   = 0;    u32 count3, count4, num_contours = 0;    s32 error;    	error = ft_stroke_border_get_counts( stroker->borders + 0, &count1, &count2 );	if ( error ) goto Exit;    error = ft_stroke_border_get_counts( stroker->borders + 1, &count3, &count4 );    if ( error ) goto Exit;    num_points   = count1 + count3;    num_contours = count2 + count4;Exit:    *anum_points   = num_points;    *anum_contours = num_contours;    return error;}/**  The following is very similar to FT_Outline_Decompose, except*  that we do support opened paths, and do not scale the outline.*/static s32 FT_Stroker_ParseOutline(FT_Stroker *stroker, GF_Path*  outline){	GF_Point2D   v_last;	GF_Point2D   v_control;	GF_Point2D   v_start;	GF_Point2D*  point;	GF_Point2D*  limit;	u8 *tags;	s32 error;	u32 n;         /* index of contour in outline     */	u32 first;     /* index of first point in contour */	s32 tag;       /* current point's state           */	if ( !outline || !stroker )	  return -1;	first = 0;	for ( n = 0; n < outline->n_contours; n++ ) {	  s32 last;  /* index of last point in contour */	  	  last  = outline->contours[n];	  limit = outline->points + last;	  v_start = outline->points[first];	  v_last  = outline->points[last];	  v_control = v_start;	  point = outline->points + first;	  tags  = outline->tags  + first;	  tag = tags[0];	  /* A contour cannot start with a cubic control point! */	  if ( tag == GF_PATH_CURVE_CUBIC )		  goto Invalid_Outline;	  /* check first point to determine origin */	  if ( tag == GF_PATH_CURVE_CONIC ) {		  /* First point is conic control.  Yes, this happens. */		  if ( outline->tags[last] & GF_PATH_CURVE_ON ) {			  /* start at last point if it is on the curve */			  v_start = v_last;			  limit--;		  } else {			  /* if both first and last points are conic,         */			  /* start at their middle and record its position    */			  /* for closure                                      */			  v_start.x = ( v_start.x + v_last.x ) / 2;			  v_start.y = ( v_start.y + v_last.y ) / 2;			  v_last = v_start;		  }		  point--;		  tags--;	  }	  error = FT_Stroker_BeginSubPath(stroker, &v_start);	  if ( error )		  goto Exit;	  while ( point < limit ) {		  point++;		  tags++;		  tag = tags[0];		  switch ( tag ) {		  case GF_PATH_CURVE_ON:  /* emit a single line_to */		  case GF_PATH_CLOSE:  /* emit a single line_to */		  {			  GF_Point2D  vec;			  vec.x = point->x;			  vec.y = point->y;			  error = FT_Stroker_LineTo( stroker, &vec, (point == limit) ? 1 : 0 );			  if ( error )				  goto Exit;			  continue;		  }		  case GF_PATH_CURVE_CONIC:  /* consume conic arcs */			  v_control.x = point->x;			  v_control.y = point->y;		Do_Conic:			  if ( point < limit ) {				  GF_Point2D  vec;				  GF_Point2D  v_middle;				  point++;				  tags++;				  tag = tags[0];				  vec = point[0];				  if ( tag & GF_PATH_CURVE_ON) {					  error = FT_Stroker_ConicTo( stroker, &v_control, &vec );					  if ( error )						  goto Exit;					  continue;				  }				  if ( tag != GF_PATH_CURVE_CONIC )					  goto Invalid_Outline;				  v_middle.x = ( v_control.x + vec.x ) / 2;				  v_middle.y = ( v_control.y + vec.y ) / 2;				  error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );				  if ( error )					  goto Exit;				  v_control = vec;				  goto Do_Conic;			  }			  error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );			  goto Close;		  default:  /* GF_PATH_CURVE_CUBIC */		  {			  GF_Point2D  vec1, vec2;			  if ( point + 1 > limit                             ||				  tags[1] != GF_PATH_CURVE_CUBIC )				  goto Invalid_Outline;

⌨️ 快捷键说明

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