Ejemplo n.º 1
0
FskErr
FskFramePolygon(
	UInt32					nPts,
	const FskFixedPoint2D	*pts,
	FskFixed				strokeWidth,
	FskFixed				jointSharpness,
	const FskColorSource	*frameColor,
	const FskFixedMatrix3x2	*M,
	UInt32					quality,
	FskConstRectangle		clipRect,
	FskBitmap				dstBM
)
{
	FskErr					err;
	const FskColorSource	*frameFillColors[2];

	if (frameColor->dashCycles != 0)	/* Do special processing for dashed lines: @@@ should have endcap spec for dashes */
		return FrameDashedPolyLine(nPts, pts, strokeWidth, jointSharpness, kFskLineEndCapClosed|kFskLineEndCapButt, frameColor, M, quality, clipRect, dstBM);

	if (M)	strokeWidth = ScaleStrokeWidth(strokeWidth, M);

	if (	(strokeWidth <= FIXED_ONE)
		&&	(frameColor->type == kFskColorSourceTypeConstant)
	) {
		if (quality == 0) {
			FskConstColorRGB frColor = (FskConstColorRGB)(void*)(&(((const FskColorSourceConstant*)(void*)frameColor)->color));
			err = FrameJaggyNarrowPolyLine(     nPts, pts,   1, frColor,              M, clipRect, dstBM);
		} else {
			frameFillColors[0] = frameColor;
			frameFillColors[1] = NULL;
			err = FskAAPolygonContours(1, &nPts, pts, FIXED_ONE, frameFillColors, -1, M, clipRect, dstBM);
		}
	}
	else {
		FskGrowableFixedPoint2DArray	pgon		= NULL;
		UInt32							n;
		FskFixedPoint2D					*p;

		BAIL_IF_ERR(err = FskWidePolyLineToPolygon(nPts, pts, strokeWidth, jointSharpness, kFskLineEndCapClosed, M, &pgon));
		BAIL_IF_ZERO((n = FskGrowableFixedPoint2DArrayGetItemCount(pgon)), err, kFskErrNothingRendered);
		BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayGetPointerToItem(pgon, 0, (void**)(void*)(&p)));
		if (quality == 0) {
			err = FillJaggyPolygonContours(1, &n, p,     frameColor,      kFskFillRuleNonZero, NULL, clipRect, dstBM);
		} else {
			frameFillColors[0] = NULL;
			frameFillColors[1] = frameColor;
			err = FskAAPolygonContours(    1, &n, p, -1, frameFillColors, kFskFillRuleNonZero, NULL, clipRect, dstBM);
		}

	bail:
		if (pgon != NULL)	FskGrowableFixedPoint2DArrayDispose(pgon);
	}

	return err;
}
Ejemplo n.º 2
0
FskErr
FskWidePolyLineToPolygon(
	UInt32							nPts,
	const FskFixedPoint2D			*pts,
	FskFixed						strokeWidth,
	FskFixed						jointSharpness,
	UInt32							endCaps,
	const FskFixedMatrix3x2			*M,
	FskGrowableFixedPoint2DArray	*polygonHandle
)
{
	FskErr							err;
	FskGrowableFixedPoint2DArray	poly, back = NULL;
	SInt32							n;
	const FskFixedPoint2D			*p0, *p1;
	FskFixedPoint2D					pt;
	LineSeg							seg0, seg1;
	MakeEndCap						endCap;
	MakeJoin						join;

	BAIL_IF_TRUE((jointSharpness < 0), err, kFskErrInvalidParameter);
	BAIL_IF_NULL(polygonHandle, err, kFskErrInvalidParameter);

	/* Select the join proc */
	if (jointSharpness < FIXED_ONE) {			/* Rounded */
		join = RoundedJoin;
		n = nPts * 8;
	}
	else if (jointSharpness == FIXED_ONE) {		/* Beveled */
		join = BeveledJoin;
		n = nPts * 3;
	}
	else {										/* Mitered */
		join = MiteredJoin;
		n = nPts * 2;
		seg0.sinMiterLimit = seg1.sinMiterLimit = FskFixDiv(FRACT_ONE, jointSharpness);
	}

	/* Convert closed 2 point polylines into open ones with compatible endcaps */
	if ((nPts == 2) && ((endCaps & kFskLineEndCapClosed) != 0)) {
		endCaps = (jointSharpness < FIXED_ONE) ? kFskLineEndCapRound : kFskLineEndCapButt;
	}

	/* Make sure a polygon is allocated */
	if (*polygonHandle == NULL) {
		BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayNew(n, polygonHandle));
	}
	else {
		BAIL_IF_ERR(err = FskGrowableFixedPoint2DArraySetItemCount(*polygonHandle, 0));
	}
	poly = *polygonHandle;

	BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayNew(n, &back));

	seg0.strokeWidth = seg1.strokeWidth = strokeWidth;

	/* Generate the polygon from the polyline description */
	switch (endCaps) {
		case kFskLineEndCapRound:
			endCap = RoundEndCap;
			seg0.arcRelTol = seg1.arcRelTol = FskFracSqrt(FskFixedNDiv(LINEAR_TOLERANCE, strokeWidth, 31));
			goto openLine;

		case kFskLineEndCapSquare:
			endCap = SquareEndCap;
			goto openLine;

		case kFskLineEndCapButt:
			endCap = ButtEndCap;

		openLine:
			p0 = pts;
			p1 = p0 + 1;
			for (n = nPts - 2; !InitLineSeg(p0, p1, M, &seg0) && (n > 0); p1++, n--) ;	/* Get the first nondegenerate segment */
			BAIL_IF_ERR(err = (*endCap)(&seg0, 0, poly));
			seg1 = seg0;	/* This should take care of the case with just 2 points */
			for (p0 = p1++; n-- > 0; p0 = p1++) {
				if (InitLineSeg(p0, p1, M, &seg1)) {
					BAIL_IF_ERR(err = (*join)(&seg0, &seg1, poly, back));
					seg0 = seg1;	/* Only shift nondegenerate segments */
				}
			}
			BAIL_IF_ERR(err = (*endCap)(&seg1, 1, poly));
			break;

		case kFskLineEndCapClosed:
//		case kFskLineEndCapClosed|kFskLineEndCapRound:	// round == 0
		case kFskLineEndCapClosed|kFskLineEndCapSquare:
		case kFskLineEndCapClosed|kFskLineEndCapButt:
			p0 = pts + nPts - 2;
			p1 = p0 + 1;
			for (n = nPts; !InitLineSeg(p0, p1, M, &seg0) && (n > 0); p0--, n--) ;	/* Nondegenerate segment coming in to the last point */
			for (p0 = p1, p1 = pts; n-- > 0; p0 = p1++) {
				if (InitLineSeg(p0, p1, M, &seg1)) {
					BAIL_IF_ERR(err = (*join)(&seg0, &seg1, poly, back));
					seg0 = seg1;	/* Only shift nondegenerate segments */
				}
			}
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayGetItem(poly, 0, &pt));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem(poly, &pt));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayGetItem(back, 0, &pt));
			BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendItem(back, &pt));
			break;
	}

	n = FskGrowableFixedPoint2DArrayGetItemCount(back);
	FskGrowableFixedPoint2DArrayGetConstPointerToItem(back, 0, (const void**)(const void*)(&p1));
	BAIL_IF_ERR(err = FskGrowableFixedPoint2DArrayAppendReversedItems(poly, p1, n));

bail:
	if (back != NULL)	FskGrowableFixedPoint2DArrayDispose(back);
	return err;
}