Пример #1
0
static FskErr
DashNextSegment(DashBuddy *db, const FskFixedPoint2D *pt)
{
	FskErr				err;
	FskFixedPoint2D		q;
	FskFixedVector2D	v;
	FskFixed			segPhase, endPhase, deltaPhase;
	FskFract			t;
	UInt32				i;

	q = db->lastPt;																										/* Point of last state change */
	v.x = pt->x - db->lastPt.x;		v.y = pt->y - db->lastPt.y;															/* Vector along the line segment */
	segPhase = FskFixedHypot(FskFixedDotProduct2D(&v, db->dashBasis+0), FskFixedDotProduct2D(&v, db->dashBasis+1));		/* Phase delta for this segment (Riemannian metric) */
	endPhase = db->dashPhase + segPhase;																				/* Phase at end of this line segment */

	while (db->thisPhaseSegment[1] <= endPhase) {
		/* We know that we're going to cross a dash segment */
		deltaPhase = db->thisPhaseSegment[1] - db->dashPhase;															/* Phase change since the last state change */
		t = FskFracDiv(deltaPhase, segPhase);		q.x += FskFracMul(t, v.x);		q.y += FskFracMul(t, v.y);			/* Compute location of next transition */
		if ((i = FskGrowableArrayGetItemCount(db->ptArray)) > 0)	DrawDashSegment(db, &q);							/* ON transitioning to OFF: end and draw this dash segment */
		else														(void)FskGrowableArrayAppendItem(db->ptArray, &q);	/* OFF transition to ON: add the start point */
		if (++(db->thisPhaseSegment) >= db->resetSegmentPhase) {														/* Advance phase segment... */
			db->thisPhaseSegment = db->dashSegmentPhases;																/* ... and reset if at the end of the phase period */
			endPhase -= db->dashPeriod;																					/* The end is getting closer */
		}
		db->dashPhase = db->thisPhaseSegment[0];																		/* Set the phase */
	}

	/* The end is still within the same dash segment */
	if ((i = FskGrowableArrayGetItemCount(db->ptArray)) > 0)	err = FskGrowableArrayAppendItem(db->ptArray, pt);	/* In the ON  state: add a kink point */
	else														err = kFskErrNone;										/* In the OFF state */
	db->dashPhase = endPhase;																							/* Update the phase */
	db->lastPt = *pt;
	return err;
}
Пример #2
0
static FskErr
BeveledJoin(const LineSeg *seg0, const LineSeg *seg1, FskGrowableFixedPoint2DArray fwdPoly, FskGrowableFixedPoint2DArray revPoly)
{
	FskErr				err			= kFskErrNone;
	FskFract			sinAng, cosAng, snmHaf, sinHaf, cosHaf;
	FskFixed			bevHafWidth, mitLength, maxElbow;
	FskFractVector2D	u;
	FskFixedVector2D	b, c, e;
	FskFixedPoint2D		p[3];

	sinAng = FskFractCrossProduct2D(&seg0->par, &seg1->par);		/* Sine of change in trajectory */
	if (sinAng == 0)												/* Collinear */
		goto bail;													/* All done */
	cosAng = FskFractDotProduct(&seg0->par.x, &seg1->par.x, 2);		/* Cosine of change in trajectory */
	if      (cosAng >  FRACT_ONE)	cosAng =  FRACT_ONE;
	else if (cosAng < -FRACT_ONE)	cosAng = -FRACT_ONE;
	cosHaf =  FskFracSqrt(FRACT_HALF - (cosAng >> 1));				/* Cosine of half the subtended angle */
	snmHaf =  FskFracSqrt(FRACT_HALF + (cosAng >> 1));				/* Sine   of half the subtended angle */
	if (snmHaf != 0) {
		sinHaf = snmHaf;
		if (sinAng < 0)	sinHaf = -sinHaf;
		u.x = FskFixedNLinear2D(seg0->par.x, cosHaf,  seg0->par.y, sinHaf, 30);	/* Unit vector to elbow, inside or outside */
		u.y = FskFixedNLinear2D(seg0->par.y, cosHaf, -seg0->par.x, sinHaf, 30);
		bevHafWidth = (FskFixed)(((FskInt64)(seg0->strokeWidth) * cosHaf / (FRACT_ONE + snmHaf) + 1) >> 1);
		c.x = FskFixedNMul(seg0->strokeWidth, u.x, 31);				/* Midpoint of bevel */
		c.y = FskFixedNMul(seg0->strokeWidth, u.y, 31);
		b.x = FskFracMul(bevHafWidth, -u.y);						/* Half-vector of bevel */
		b.y = FskFracMul(bevHafWidth,  u.x);
		mitLength = FskFixedNDiv(seg0->strokeWidth, snmHaf, 29);
		if ((maxElbow = (seg0->strokeWidth)) < seg0->length)		/* Limit the extent of the inside bevel joint */
			maxElbow = seg0->length;
		if (maxElbow < seg1->length)
			maxElbow = seg1->length;
		if (mitLength > maxElbow)
			mitLength = maxElbow;
		e.x = FskFracMul(mitLength, u.x);							/* Scaled vector to elbow, inside */
		e.y = FskFracMul(mitLength, u.y);

		if (sinAng > 0) {	/* Positive rotation */
			p[0].x = seg0->pt[1].x + c.x - b.x;						/* First bevel point */
			p[0].y = seg0->pt[1].y + c.y - b.y;
			p[1].x = seg0->pt[1].x + c.x + b.x;						/* Second bevel point */
			p[1].y = seg0->pt[1].y + c.y + b.y;
			p[2].x = seg0->pt[1].x - e.x;							/* Inside elbow */
			p[2].y = seg0->pt[1].y - e.y;
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItems(revPoly, &p[0], 2));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem( fwdPoly, &p[2]));
		}
		else {				/* Negative rotation */
			p[0].x = seg0->pt[1].x + c.x + b.x;						/* First bevel point */
			p[0].y = seg0->pt[1].y + c.y + b.y;
			p[1].x = seg0->pt[1].x + c.x - b.x;						/* Second bevel point */
			p[1].y = seg0->pt[1].y + c.y - b.y;
			p[2].x = seg0->pt[1].x - e.x;							/* Inside elbow */
			p[2].y = seg0->pt[1].y - e.y;
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItems(fwdPoly, &p[0], 2));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem( revPoly, &p[2]));
		}
	}
Пример #3
0
static FskErr
RoundedJoin(const LineSeg *seg0, const LineSeg *seg1, FskGrowableFixedPoint2DArray fwdPoly, FskGrowableFixedPoint2DArray revPoly)
{
	FskErr				err			= kFskErrNone;
	FskFract			sinAng, cosAng, snmHaf, sinHaf, cosHaf;
	FskFixed			mitLength, maxElbow;
	FskFractVector2D	u;
	FskFixedVector2D	v0, v1, e;
	FskFixedPoint2D		p[4];

	sinAng = FskFractCrossProduct2D(&seg0->par, &seg1->par);			/* Sine of change in trajectory */
	if (sinAng == 0)													/* Collinear */
		goto bail;														/* All done */
	cosAng = FskFractDotProduct(&seg0->par.x, &seg1->par.x, 2);			/* Cosine of change in trajectory */
	if      (cosAng >  FRACT_ONE)	cosAng =  FRACT_ONE;
	else if (cosAng < -FRACT_ONE)	cosAng = -FRACT_ONE;
	cosHaf =  FskFracSqrt(FRACT_HALF - (cosAng >> 1));					/* Cosine of half the subtended angle */
	snmHaf =  FskFracSqrt(FRACT_HALF + (cosAng >> 1));					/* Sine   of half the subtended angle */
	if (snmHaf != 0) {
		sinHaf = snmHaf;
		if (sinAng < 0)	sinHaf = -sinHaf;
		v0.x = FskFixedNMul(seg0->perp.x, seg0->strokeWidth, 31);		/* Perpendicular excursion from seg0 */
		v0.y = FskFixedNMul(seg0->perp.y, seg0->strokeWidth, 31);
		v1.x = FskFixedNMul(seg1->perp.x, seg0->strokeWidth, 31);		/* Perpendicular excursion from seg1 */
		v1.y = FskFixedNMul(seg1->perp.y, seg0->strokeWidth, 31);
		u.x = FskFixedNLinear2D(seg0->par.x, cosHaf,  seg0->par.y, sinHaf, 30);	/* Unit vector to elbow, inside or outside */
		u.y = FskFixedNLinear2D(seg0->par.y, cosHaf, -seg0->par.x, sinHaf, 30);
		mitLength = FskFixedNDiv(seg0->strokeWidth, snmHaf, 29);
		if ((maxElbow = (seg0->strokeWidth)) < seg0->length)			/* Limit the extent of the inside bevel joint */
			maxElbow = seg0->length;
		if (maxElbow < seg1->length)
			maxElbow = seg1->length;
		if (mitLength > maxElbow)
			mitLength = maxElbow;
		e.x = FskFracMul(mitLength, u.x);								/* Scaled vector to elbow, inside */
		e.y = FskFracMul(mitLength, u.y);

		if (sinAng > 0) {	/* Positive rotation */
			p[0].x = seg0->pt[1].x - v0.x;								/* Start of arc */
			p[0].y = seg0->pt[1].y - v0.y;
			p[2].x = seg0->pt[1].x - v1.x;								/* End of arc */
			p[2].y = seg0->pt[1].y - v1.y;
			p[1].x = seg0->pt[1].x +  e.x;								/* Outside elbow point */
			p[1].y = seg0->pt[1].y +  e.y;
			p[3].x = seg0->pt[1].x -  e.x;								/* Inside elbow point */
			p[3].y = seg0->pt[1].y -  e.y;
			BAIL_IF_ERR(err = FskTessellateRationalBezier2DRegularly(&p[0], &p[1], &snmHaf, 3, NULL, revPoly));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem(fwdPoly, &p[3]));
		}
		else {				/* Negative rotation */
			p[0].x = seg0->pt[1].x + v0.x;								/* Start of arc */
			p[0].y = seg0->pt[1].y + v0.y;
			p[2].x = seg0->pt[1].x + v1.x;								/* End of arc */
			p[2].y = seg0->pt[1].y + v1.y;
			p[1].x = seg0->pt[1].x +  e.x;								/* Outside elbow point */
			p[1].y = seg0->pt[1].y +  e.y;
			p[3].x = seg0->pt[1].x -  e.x;								/* Inside elbow point */
			p[3].y = seg0->pt[1].y -  e.y;
			BAIL_IF_ERR(err = FskTessellateRationalBezier2DRegularly(&p[0], &p[1], &snmHaf, 3, NULL, fwdPoly));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem(revPoly, &p[3]));
		}
	}
	/* else 0 degrees subtended (180 degree about face): what to do? */

bail:
	return err;
}