示例#1
0
static FskErr
FillJaggyPolygonContours(
	UInt32					nContours,
	const UInt32			*nPts,
	const FskFixedPoint2D	*pts,
	const FskColorSource	*colorSource,
	SInt32					fillRule,
	const FskFixedMatrix3x2	*M,
	FskConstRectangle		clipRect,
	FskBitmap				dstBM
)
{
	FskRectangleRecord	dstRect;
	LinkedEdge			edges[MAX_EDGES], *pEdges = edges;	/* Small polygons use auto edges, large ones need to be alloc'ed */
	UInt32				numEdges, totPts;
	FskSpan				span;
	FskErr				err = kFskErrNone;
	SInt32				n;
	const UInt32		*np;
	LinkedEdge			*pe;
	static FskInitSpanProc	initProcs[] = {
								FskInitSolidColorSpan,
								FskInitLinearGradientSpan,
								FskInitRadialGradientSpan,
								FskInitTextureSpan,
								NULL						/* Procedure span is not yet implemented */
							};
	FskInitSpanProc		initSpan;

	if (clipRect == NULL)	dstRect = dstBM->bounds;
	else					if (!FskRectangleIntersect(&dstBM->bounds, clipRect, &dstRect)) return kFskErrNothingRendered;

	for (n = nContours, np = nPts, totPts = 0; n--; )
		totPts += *np++;

	FskInitSpan(&span, dstBM, sizeof(LinkedEdge));										/* Generic span init */
	initSpan =  initProcs[((n = colorSource->type) <= kFskColorSourceTypeMax) ? n : 0];
	if ((err = (*initSpan)(&span, dstBM, M, 0, colorSource)) != kFskErrNone)			/* Specialized span init - this may bump up the edge size */
		return err;
	span.edgeBytes = (span.edgeBytes + 3) & ~3;											/* Ceil up to multiple of 4 bytes */
	if (	CANT_USE_AUTO_EDGES(totPts)																							/* Either small enough for auto storage ... */
		&&	(err = (FskMemPtrNew(totPts * CLIP_MULTIPLIER * sizeof(LinkedEdge), (FskMemPtr*)(void*)(&pEdges))) != kFskErrNone)	/* ... or we can allocate memory */
	)
		return err;																		/* Polygon is too big to render */

	for (numEdges = 0, pe = pEdges; nContours--; pts += *nPts++, numEdges += n, pe += n)
		BAIL_IF_NEGATIVE(n = TransformClipAndMakeEdges(*nPts, pts, M, &dstRect, &span, pe), err, kFskErrMemFull);
	BAIL_IF_FALSE(numEdges >= 2, err, kFskErrNothingRendered);
	err = ScanConvertLinkedEdges(numEdges, pEdges, fillRule, &span);

bail:
	if (pEdges != edges)
		FskMemPtrDispose(pEdges);	/* Deallocate big polygon edges */

	if ((span.disposeSpanData != NULL) && (span.spanData != NULL))
		span.disposeSpanData(span.spanData);

	return err;
}
示例#2
0
static FskErr
FrameJaggyNarrowPolyLine(
	UInt32					nPts,
	const FskFixedPoint2D	*pts,
	UInt32					closed,
	FskConstColorRGB		frameColor,
	const FskFixedMatrix3x2	*M,
	FskConstRectangle		clipRect,
	FskBitmap				dstBM
)
{
	FskErr					err;
	FskRectangleRecord		dstRect;
	FskFixedPoint2D			pt[3];
	const FskFixedPoint2D	*p0, *p1;
	UInt32					k;

	if (clipRect == NULL)	dstRect = dstBM->bounds;
	else					if (!FskRectangleIntersect(&dstBM->bounds, clipRect, &dstRect)) return kFskErrNothingRendered;

	if (closed) {
		p0 = pts + nPts - 1;
		p1 = pts;
	}
	else {
		p0 = pts;
		p1 = p0 + 1;
		nPts--;
	}

	if (M == NULL) {
		for (k = 0; nPts--; p0 = p1++) {
			pt[0] = *p0;
			pt[1] = *p1;
			if (FskClipLine2D(&dstRect, pt+0, pt+1)) {
				FskDrawClippedJaggedLine(pt+0, pt+1, frameColor, dstBM);
				k++;
			}
		}
	}
	else {
		FskTransformFixedRowPoints2D(p0, 1, M, pt+0);					/* Transform last/first point */
		for (k = 0; nPts--; pt[0] = pt[2], p1++) {
			FskTransformFixedRowPoints2D(p1, 1, M, pt+2);				/* Transform next point, and save it for the next iteration */
			pt[1] = pt[2];												/* Make copy of transformed point for clipper */
			if (FskClipLine2D(&dstRect, pt+0, pt+1)) {					/* Both pt[0] and pt[1] have been clipped */
				FskDrawClippedJaggedLine(pt+0, pt+1, frameColor, dstBM);
				k++;
			}
		}
	}

	err =  k ? kFskErrNone : kFskErrNothingRendered;

	return err;
}
示例#3
0
FskErr winTextBox(FskTextEngineState state, FskBitmap bits, const char *text, UInt32 textLen, FskConstRectangle bounds, FskConstRectangleFloat boundsFloat, FskConstRectangle clipRect, FskConstColorRGBA color, UInt32 blendLevel, UInt32 textSize, UInt32 textStyle, UInt16 hAlign, UInt16 vAlign, FskFixed textExtra, const char *fontName, FskTextFormatCache formatCacheIn)
{
	FskTextFormatCacheGDI formatCache = (FskTextFormatCacheGDI)formatCacheIn;
	RECT r;
	UINT flags = DT_SINGLELINE | DT_NOPREFIX | ((kFskTextTruncateEnd & textStyle) ? DT_END_ELLIPSIS : 0);
	Boolean direct = (blendLevel >= 255) && (NULL != bits->hbmp) &&
			!((kFskTextOutline | kFskTextOutlineHeavy) & textStyle) && !bits->hasAlpha;
	FskBitmap scratchBits = NULL;
	HFONT font;
	HDC dc = direct ? bits->hdc : state->dc;
	HGDIOBJ saveFont;
	FskRectangleRecord clip;
	unsigned char scratchBuffer[256];
	int saveCharExtra;

	// combine bounds and clip to total clip
	if (NULL == clipRect) {
		clip = *bounds;
	}
	else {
		if (false == FskRectangleIntersect(clipRect, bounds, &clip))
			return kFskErrNone;
	}

	if (direct) {
		if (clipRect)
			IntersectClipRect(dc, clipRect->x, clipRect->y, clipRect->x + clipRect->width, clipRect->y + clipRect->height);
		SetRect(&r, bounds->x, bounds->y, bounds->x + bounds->width, bounds->y + bounds->height);

		SetTextColor(dc, RGB(color->r, color->g, color->b));
	}
	else {
		FskErr err;
		const UInt32 kFskTextOffscreenFormat = kFskBitmapFormat24BGR;

		/* Negative width below indicates that we want a native bitmap */
		err = FskBitmapNew(-bounds->width, bounds->height, kFskTextOffscreenFormat, &scratchBits);
		if (kFskErrNone == err)
			SetRect(&r, 0, 0, bounds->width, bounds->height);
		else {
			FskRectangleRecord b;

			err = winTextGetBounds(state, bits, text, textLen, textSize, textStyle, textExtra, fontName, &b, NULL, formatCacheIn);
			if (err) return err;

			err = FskBitmapNew(-b.width, b.height, kFskTextOffscreenFormat, &scratchBits);
			if (err) return err;

			SetRect(&r, 0, 0, b.width, b.height);
		}

		dc = scratchBits->hdc;
		SetTextColor(dc, RGB(255, 255, 255));
	}

	if (NULL == formatCache)
		saveFont = syncFont(textSize, textStyle, fontName, &font, state);
	else
		saveFont = SelectObject(dc, formatCache->font);

	saveCharExtra = SetTextCharacterExtra(dc, textExtra >> 16);

#if 0
	switch (hAlign) {
		case kFskTextAlignLeft:
		default:
			flags |= DT_LEFT;
			break;

		case kFskTextAlignCenter:
			flags |= DT_CENTER;
			break;

		case kFskTextAlignRight:
			flags |= DT_RIGHT;
			break;
	}

	switch (vAlign) {
		case kFskTextAlignTop:
		default:
			flags |= DT_TOP;
			break;

		case kFskTextAlignCenter:
			flags |= DT_VCENTER;
			break;

		case kFskTextAlignBottom:
			flags |= DT_BOTTOM;
			break;
	}
#endif

	{
	SIZE sz;
	UINT align;
	SInt32 y;
	char *encodedText = (char *)scratchBuffer;
	UInt32 encodedTextLen = sizeof(scratchBuffer);
	if (kFskErrNone != FskTextUTF8ToUnicode16NENoAlloc(text, textLen, (UInt16 *)scratchBuffer, &encodedTextLen)) {
		if (kFskErrNone != FskMemPtrNew(encodedTextLen, &encodedText)) {
			FskBitmapDispose(scratchBits);
			goto done;
		}
		FskTextUTF8ToUnicode16NENoAlloc(text, textLen, (UInt16 *)encodedText, &encodedTextLen);
	}

	encodedTextLen >>= 1;
	remapForMicrosoft((UInt16 *)encodedText, encodedTextLen);

	if (kFskTextTruncateCenter & textStyle) {
		// work hard to truncate the center, since Windows doesn't support this directly
		SIZE size;
		int *widths;

		if (kFskErrNone == FskMemPtrNew(sizeof(int) * encodedTextLen, (FskMemPtr *)&widths)) {
			int maxC, i, fitWidth = (r.right - r.left);
			GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, 32768, &maxC, widths, &size);
			if (size.cx > fitWidth) {
				SInt32 currentWidth = size.cx;
				SInt32 truncBegin, truncEnd;
				WCHAR ellipsis = 0x2026;
				SIZE ellipsisSize;
				UInt16 *uniChars = (UInt16 *)encodedText;

				for (i = encodedTextLen - 1; i > 0; i--)
					widths[i] -= widths[i - 1];

				GetTextExtentPoint32W(dc, (LPWSTR)&ellipsis, 1, &ellipsisSize);		//@@ could use ellipsisWidth in cache here
				fitWidth -= ellipsisSize.cx;

				if (fitWidth > 0) {
					Boolean phase = true;		// start towards the end
					truncBegin = truncEnd = encodedTextLen / 2;
					while ((currentWidth > fitWidth) && ((truncEnd - truncBegin) != encodedTextLen)) {
						if (phase) {
							if (truncEnd < (SInt32)encodedTextLen) {
								currentWidth -= widths[truncEnd];
								truncEnd += 1;
							}
						}
						else {
							if (0 != truncBegin) {
								truncBegin -= 1;
								currentWidth -= widths[truncBegin];
							}
						}
						phase = !phase;
					}
					FskMemMove(&uniChars[truncBegin + 1], &uniChars[truncEnd], (encodedTextLen - truncEnd) * 2);
					uniChars[truncBegin] = ellipsis;
					encodedTextLen -= (truncEnd - truncBegin);
					encodedTextLen += 1;

					flags &= ~DT_END_ELLIPSIS;
				}
			}

			FskMemPtrDispose(widths);
		}
	}

#if 0
	DrawTextW(dc, (LPWSTR)encodedText, encodedTextLen, &r, flags);
#else
	if (kFskTextTruncateEnd & textStyle) {
		int fitChars;
		int stackWidths[256], *widths, width = r.right - r.left;
		WCHAR ellipsis = 0x2026;
		SIZE ellipsisSz;

		if (encodedTextLen < 256)
			widths = stackWidths;
		else {
			if (kFskErrNone != FskMemPtrNew(sizeof(int) * encodedTextLen, (FskMemPtr *)&widths)) {
				widths = stackWidths;
				encodedTextLen = 256;
			}
		}

		GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, width, &fitChars, widths, &sz);
		if ((UInt32)fitChars < encodedTextLen) {
			// remove trailing white space
			if (formatCache) {
				if (!formatCache->haveEllipsisWidth) {
					GetTextExtentExPointW(dc, (WCHAR *)&ellipsis, 1, 0, NULL, NULL, &ellipsisSz);
					formatCache->haveEllipsisWidth = true;
					formatCache->ellipsisWidth = ellipsisSz.cx;
				}
				else
					ellipsisSz.cx = formatCache->ellipsisWidth;
			}
			else
				GetTextExtentExPointW(dc, (WCHAR *)&ellipsis, 1, 0, NULL, NULL, &ellipsisSz);

			if (width > ellipsisSz.cx) {
				width -= ellipsisSz.cx;

				while (fitChars > 2) {
					UInt16 c = ((UInt16 *)encodedText)[fitChars - 2];

					if ((32 != c) && (9 != c) && (0x3000 != c))
						break;

					fitChars -= 1;
				}

				// truncate if needed to make room for the ellipsis
				while ((widths[fitChars - 1] > width) && (fitChars > 2))
					fitChars -= 1;

				// add ellipsis
				((UInt16 *)encodedText)[fitChars - 1] = 0x2026;		// ellipsis
				encodedTextLen = fitChars;
			}
			else
				encodedTextLen = 0;
		}

		if (widths != stackWidths)
			FskMemPtrDispose(widths);
	}
	else {
		if (kFskTextAlignCenter == vAlign)
			GetTextExtentExPointW(dc, (WCHAR *)encodedText, encodedTextLen, 0, NULL, NULL, &sz);
	}

	if (kFskTextAlignCenter == vAlign) {
		y = (r.top + r.bottom - sz.cy) >> 1;
		align = TA_TOP;
	}
	else
	if (kFskTextAlignTop == vAlign) {