graphicsdeviceinterface/bitgdi/sbit/ROUNDREC.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/bitgdi/sbit/ROUNDREC.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,230 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <fntstore.h>
+#include <bitmap.h>
+#include <bitstd.h>
+#include <bitdev.h>
+#include "BITPANIC.H"
+#include <bitdraw.h>
+#include <graphics/fbsrasterizer.h>
+
+/**
+Draws and fills a rectangle with rounded corners.
+
+The function provides a concrete implementation of the pure virtual
+function <code>CGraphicsContext::DrawRoundRect()</code>. The function
+behaviour is the same as documented in that class.
+*/
+EXPORT_C void CFbsBitGc::DrawRoundRect(const TRect& aRect,const TSize& aSize)
+	{
+	if (CheckDevice(aRect))
+		return;
+
+	TSize ellsize(aSize);
+	ellsize.iWidth <<= 1;
+	ellsize.iHeight <<= 1;
+
+	if (ellsize.iWidth < 3 || ellsize.iHeight < 3)
+		{
+		DrawRect(aRect);
+		return;
+		}
+
+	if (aRect.Width() < ellsize.iWidth && aRect.Height() < ellsize.iHeight)
+		{
+		DrawEllipse(aRect);
+		return;
+		}
+
+	TRect rcpy(aRect);
+	rcpy.Move(iOrigin);
+	iDevice->TruncateRect(rcpy);
+	ellsize.iWidth = Min(rcpy.Width(),ellsize.iWidth);
+	ellsize.iHeight = Min(rcpy.Height(),ellsize.iHeight);
+
+	TRect clippedBoundingRect(rcpy);
+	clippedBoundingRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1);
+	if (!clippedBoundingRect.Intersects(iUserClipRect))
+		return;
+
+	SetupDevice();
+	iDevice->DrawingBegin(&iBrushBitmap);
+	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
+
+	if (iBrushStyle != ENullBrush)
+		RoundRectFill(rcpy,ellsize);
+
+	if (iPenStyle != ENullPen && iPenSize.iWidth > 0 && iPenSize.iHeight > 0)
+		RoundRectOutline(rcpy,ellsize);
+
+	if (brushRasterizer)
+		{
+		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
+		}
+	iDevice->DrawingEnd(&iBrushBitmap);
+	}
+
+// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
+void CFbsBitGc::RoundRectFill(const TRect& aRect,TSize aSize)
+	{
+	TRect rcpy(aRect);
+	if (iPenSize.iWidth < 1 || iPenSize.iHeight < 1)
+		rcpy.Grow(1,1);
+	AddRect(rcpy);
+
+	if (rcpy.iBr.iX - rcpy.iTl.iX < aSize.iWidth)
+		aSize.iWidth = rcpy.Width();
+	if (rcpy.iBr.iY - rcpy.iTl.iY < aSize.iHeight)
+		aSize.iHeight = rcpy.Height();
+
+	TInt xoff = rcpy.Width() - aSize.iWidth;
+	TInt yoff = rcpy.Height() - aSize.iHeight;
+	TPoint tl,tr,bl,br;
+	TInt prevlev = 0;
+	TBool draw = EFalse;
+
+	const TInt limit = iDefaultRegionPtr->Count();
+	for (TInt count = 0; count < limit; count++)
+		{
+		iClipRect = (*iDefaultRegionPtr)[count];
+		if (UserClipRect(iClipRect))
+			continue;
+		if (!iClipRect.Intersects(aRect))
+			continue;
+
+		draw = ETrue;
+		iClipRect.Intersection(aRect);
+
+		TEllipse ellipse;
+		ellipse.Construct(TRect(rcpy.iTl,rcpy.iTl + aSize));
+		ellipse.SingleStep(tl,tr,bl,br);
+		prevlev = tl.iY;
+
+		while (!ellipse.SingleStep(tl,tr,bl,br))
+			{
+			if (tl.iY == prevlev)
+				continue;
+
+			tl.iX++;
+			tr.iX += xoff - 1;
+			bl.iX++;
+			bl.iY += yoff;
+			br.iX += xoff - 1;
+			br.iY += yoff;
+
+			ClipFillLine(tl,tr);
+			ClipFillLine(bl,br);
+
+			prevlev = tl.iY;
+			}
+
+		iDevice->iDrawDevice->UpdateRegion(iClipRect);
+		}
+
+	if (!draw)
+		return;
+
+	if (tl.iY >= bl.iY)
+		{
+		tl.iY--;
+		br.iY++;
+		}
+
+	tl.iX++;
+	tl.iY++;
+	br.iX += xoff;
+	br.iY += yoff;
+
+	RectFill(TRect(tl,br));
+	}
+
+void CFbsBitGc::RoundRectOutline(const TRect& aRect,TSize aSize)
+	{
+	TRect rcpy(aRect);
+	const TInt halfpenwidth = (iPenSize.iWidth + 1) >> 1;
+	const TInt halfpenheight = (iPenSize.iWidth + 1) >> 1;
+	rcpy.Grow(halfpenwidth,halfpenheight);
+	AddRect(rcpy);
+
+	if (aRect.Width() < aSize.iWidth)
+		aSize.iWidth = aRect.Width();
+	if (aRect.Height() < aSize.iHeight)
+		aSize.iHeight = aRect.Height();
+
+	TPoint tl,tr,bl,br;
+	const TInt xoff = aRect.Width() - aSize.iWidth;
+	const TInt yoff = aRect.Height() - aSize.iHeight;
+	const TInt dotparam = iDotParam;
+
+	const TInt limit = iDefaultRegionPtr->Count();
+	for (TInt count = 0; count < limit; count++)
+		{
+		iClipRect = (*iDefaultRegionPtr)[count];
+		if (!iClipRect.Intersects(rcpy))
+			continue;
+		iClipRect.Intersection(rcpy);
+		if (UserClipRect(iClipRect))
+			continue;
+
+		iDotParam = Max(iPenSize.iWidth >> 1,iPenSize.iHeight >> 1);
+		TInt column = aRect.iTl.iX + (aSize.iWidth >> 1);
+		TInt lastcolumn = aRect.iTl.iX + xoff + (aSize.iWidth >> 1);
+
+		for (; column < lastcolumn; column++)
+			{
+			PenDrawClipped(TPoint(column,aRect.iTl.iY));
+			PenDrawClipped(TPoint(column,aRect.iBr.iY - 1));
+			iDotParam += iDotDirection;
+			}
+
+		TEllipse ellipse;
+		ellipse.Construct(TRect(aRect.iTl,aRect.iTl + aSize));
+		while (!ellipse.SingleStep(tl,tr,bl,br))
+			{
+			tr.iX += xoff;
+			bl.iY += yoff;
+			br.iX += xoff;
+			br.iY += yoff;
+
+			PenDrawClipped(tl);
+			PenDrawClipped(tr);
+			PenDrawClipped(bl);
+			PenDrawClipped(br);
+
+			iDotParam += iDotDirection;
+			}
+
+		if (tl.iY >= bl.iY)
+			{
+			tl.iY--;
+			bl.iY++;
+			}
+
+		bl.iY += yoff;
+
+		for (column = tl.iY + 1; column < bl.iY; column++)
+			{
+			PenDrawClipped(TPoint(aRect.iTl.iX,column));
+			PenDrawClipped(TPoint(aRect.iBr.iX - 1,column));
+			iDotParam += iDotDirection;
+			}
+
+		iDevice->iDrawDevice->UpdateRegion(iClipRect);
+		}
+
+	iDotParam = dotparam;
+	}
+