graphicsdeviceinterface/bitgdi/sbit/PIEARC.CPP
author Faisal Memon <faisal.memon@nokia.com>
Fri, 14 May 2010 15:41:33 +0100
branchNewGraphicsArchitecture
changeset 64 5c983aa672ea
parent 0 5d03bc08d59c
permissions -rw-r--r--
Merge 1. Pull in cpp files in the performance enhanced Khronos RI OVG files which are newly added. I've ignored platform-specific cpp files for linux, macosx, and null operating systems because this local solution has its own platform glue (i.e. facility to target Bitmaps but no full windowing support). I've ignored sfEGLInterface.cpp because this is used as a bridge to go from EGL to Nokia's Platsim which offers an EGL service. That's not relevant to this implementation because this is ARM side code, not Intel side. I just left a comment to sfEGLInterface.cpp in case we need to pick up this later on. The current code compiles on winscw. Prior to this fix, the code works on winscw, and can launch the SVG tiger (tiger.exe). That takes about 20 seconds to render. I hope to always be able to show this icon on each commit, and the plan is for the render time to reduce with this series of submissions. On this commit, the tiger renders ok in 20 seconds.

// 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 <bitstd.h>
#include <bitdev.h>
#include "BITPANIC.H"
#include <bitdraw.h>
#include <graphics/fbsrasterizer.h>

// TPieArc

class TArc : public TEllipse
	{
public:
	void Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd);
	TBool SingleStep(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
	void Step(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
public:
	TPoint iStart;
	TPoint iEnd;
private:
	TBool iTlquad;
	TBool iTrquad;
	TBool iBlquad;
	TBool iBrquad;
	TBool iStartquadenabled;
	TBool iEndquadenabled;
	TBool iStartquaddone;
	TBool iEndquaddone;
	TInt iStartquad;
	TInt iEndquad;
	TBool iSlice;
	};

void TArc::Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd)
	{
	iStart=Intersection(aRect,aStart);
	iEnd=Intersection(aRect,aEnd);
	TEllipse::Construct(aRect);
	iTlquad=EFalse;
	iTrquad=EFalse;
	iBlquad=EFalse;
	iBrquad=EFalse;
	iStartquadenabled=EFalse;
	iEndquadenabled=EFalse;
	iSlice=EFalse;
	iStartquad=0;
	iEndquad=0;
	TPoint center=aRect.Center();
	if (iStart.iX>=center.iX) iStartquad=1;
	if (iStart.iY>=center.iY) iStartquad+=2;
	if (iEnd.iX>=center.iX) iEndquad=1;
	if (iEnd.iY>=center.iY) iEndquad+=2;
	if (iStartquad!=iEndquad)
		{
		if (iStartquad==0 && iEndquad==1)
			{
			iBlquad=ETrue;
			iBrquad=ETrue;
			}
		else if (iStartquad==0 && iEndquad==3)
			iBlquad=ETrue;
		else if (iStartquad==1 && iEndquad==2)
			iTlquad=ETrue;
		else if (iStartquad==1 && iEndquad==3)
			{
			iTlquad=ETrue;
			iBlquad=ETrue;
			}
		else if (iStartquad==2 && iEndquad==0)
			{
			iTrquad=ETrue;
			iBrquad=ETrue;
			}
		else if (iStartquad==2 && iEndquad==1)
			iBrquad=ETrue;
		else if (iStartquad==3 && iEndquad==0)
			iTrquad=ETrue;
		else if (iStartquad==3 && iEndquad==2)
			{
			iTlquad=ETrue;
			iTrquad=ETrue;
			}
		}
	else if (iStart==iEnd)
		{
		iTlquad=ETrue;
		iTrquad=ETrue;
		iBlquad=ETrue;
		iBrquad=ETrue;
		}
	else
		{
		iSlice=ETrue;
		if (iStartquad==0 && (iStart.iX<iEnd.iX || iStart.iY>iEnd.iY))
			{
			iTrquad=ETrue;
			iBlquad=ETrue;
			iBrquad=ETrue;
			iSlice=EFalse;
			}
		else if (iStartquad==1 && (iStart.iX<iEnd.iX || iStart.iY<iEnd.iY))
			{
			iTlquad=ETrue;
			iBlquad=ETrue;
			iBrquad=ETrue;
			iSlice=EFalse;
			}
		else if (iStartquad==2 && (iStart.iX>iEnd.iX || iStart.iY>iEnd.iY))
			{
			iTlquad=ETrue;
			iTrquad=ETrue;
			iBrquad=ETrue;
			iSlice=EFalse;
			}
		else if (iStartquad==3 && (iStart.iX>iEnd.iX || iStart.iY<iEnd.iY))
			{
			iTlquad=ETrue;
			iTrquad=ETrue;
			iBlquad=ETrue;
			iSlice=EFalse;
			}
		}
	if (iStartquad==1 || iStartquad==2)
		iStartquadenabled=ETrue;
	if (iEndquad==0 || iEndquad==3)
		iEndquadenabled=ETrue;
	iStartquaddone=EFalse;
	iEndquaddone=EFalse;
	}

TBool TArc::SingleStep(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,
					   TBool& aDoTr,TPoint& aBottomLeft,TBool& aDoBl,
					   TPoint& aBottomRight,TBool& aDoBr)
	{
	TBool finished=TEllipse::SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
	Step(aTopLeft,aDoTl,aTopRight,aDoTr,aBottomLeft,aDoBl,aBottomRight,aDoBr);

	return finished;
	}

void TArc::Step(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,TBool& aDoTr,
				TPoint& aBottomLeft,TBool& aDoBl,TPoint& aBottomRight,TBool& aDoBr)
	{
	aDoTl=iTlquad;
	aDoTr=iTrquad;
	aDoBl=iBlquad;
	aDoBr=iBrquad;
	if (!iStartquaddone)
		{
		if (!iStartquadenabled)
			{
			if (iStartquad==0 && aTopLeft.iX<=iStart.iX && aTopLeft.iY>=iStart.iY)
				{
				iStartquadenabled=ETrue;
				iStartquaddone=ETrue;
				}
			if (iStartquad==3 && aBottomRight.iX>=iStart.iX && aBottomRight.iY<=iStart.iY)
				{
				iStartquadenabled=ETrue;
				iStartquaddone=ETrue;
				}
			}
		else
			{
			if (iStartquad==1 && (aTopRight.iX>iStart.iX || aTopRight.iY>iStart.iY))
				{
				iStartquadenabled=EFalse;
				iStartquaddone=ETrue;
				}
			if (iStartquad==2 && (aBottomLeft.iX<iStart.iX || aBottomLeft.iY<iStart.iY))
				{
				iStartquadenabled=EFalse;
				iStartquaddone=ETrue;
				}
			}
		}
	if (!iEndquaddone)
		{
		if (iEndquadenabled)
			{
			if (iEndquad==0 && (aTopLeft.iX<iEnd.iX || aTopLeft.iY>iEnd.iY))
				{
				iEndquadenabled=EFalse;
				iEndquaddone=ETrue;
				}
			if (iEndquad==3 && (aBottomRight.iX>iEnd.iX || aBottomRight.iY<iEnd.iY))
				{
				iEndquadenabled=EFalse;
				iEndquaddone=ETrue;
				}
			}
		else
			{
			if (iEndquad==1 && aTopRight.iX>=iEnd.iX && aTopRight.iY>=iEnd.iY)
				{
				iEndquadenabled=ETrue;
				iEndquaddone=ETrue;
				}
			if (iEndquad==2 && aBottomLeft.iX<=iEnd.iX && aBottomLeft.iY<=iEnd.iY)
				{
				iEndquadenabled=ETrue;
				iEndquaddone=ETrue;
				}
			}
		}
	if (iStartquad!=iEndquad)
		{
		if (iStartquadenabled)
			{
			if (iStartquad==0) aDoTl=ETrue;
			else if (iStartquad==1) aDoTr=ETrue;
			else if (iStartquad==2) aDoBl=ETrue;
			else if (iStartquad==3) aDoBr=ETrue;
			}
		if (iEndquadenabled)
			{
			if (iEndquad==0) aDoTl=ETrue;
			else if (iEndquad==1) aDoTr=ETrue;
			else if (iEndquad==2) aDoBl=ETrue;
			else if (iEndquad==3) aDoBr=ETrue;
			}
		}
	else
		{
		if (iSlice)
			{
			if (iStartquadenabled && iEndquadenabled)
				{
				if (iStartquad==0) aDoTl=ETrue;
				else if (iStartquad==1) aDoTr=ETrue;
				else if (iStartquad==2) aDoBl=ETrue;
				else if (iStartquad==3) aDoBr=ETrue;
				}
			}
		else
			{
			if (iStartquadenabled || iEndquadenabled)
				{
				if (iStartquad==0) aDoTl=ETrue;
				else if (iStartquad==1) aDoTr=ETrue;
				else if (iStartquad==2) aDoBl=ETrue;
				else if (iStartquad==3) aDoBr=ETrue;
				}
			}
		}
	if (aTopLeft.iX==aTopRight.iX)
		{
		if (aDoTl && aDoTr) aDoTr=EFalse;
		if (aDoBl && aDoBr) aDoBr=EFalse;
		}
	}

//
// Pie and Arc drawing functions
//

/**
Draws an arc.

The function provides a concrete implementation of the pure virtual
function <code>CGraphicsContext::DrawArc()</code>. The function
behaviour is the same as documented in that class.
*/
EXPORT_C void CFbsBitGc::DrawArc(const TRect& aRect,const TPoint& aStartradius,
								 const TPoint& aEndradius)
	{
	if (!iPenStyle || !iPenSize.iWidth  || !iPenSize.iHeight || aRect.IsEmpty() || CheckDevice(aRect))
		return;

	TRect rcpy(aRect);
	rcpy.Move(iOrigin);
	iDevice->TruncateRect(rcpy);
	TRect arcBoundingRect(rcpy);
	arcBoundingRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
	if (!arcBoundingRect.Intersects(iUserClipRect))
		return;

	SetupDevice();
	iDevice->DrawingBegin();
	PieArcOutline(rcpy,aStartradius+iOrigin,aEndradius+iOrigin,EFalse);
	iDevice->DrawingEnd();
	}

/**
Draws and fills a pie slice.

The function provides a concrete implementation of the pure virtual
function <code>CGraphicsContext::DrawPie()</code>. The function
behaviour is the same as documented in that class.
*/
EXPORT_C void CFbsBitGc::DrawPie(const TRect& aRect,const TPoint& aStartradius,
								 const TPoint& aEndradius)
	{
	if (CheckDevice(aRect))
		return;

	TRect rcpy(aRect);
	rcpy.Move(iOrigin);
	iDevice->TruncateRect(rcpy);
	TRect pieBoundingRect(rcpy);
	pieBoundingRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
	if (!pieBoundingRect.Intersects(iUserClipRect))
		return;

	TPoint startIntersect = aStartradius + iOrigin, endIntersect = aEndradius + iOrigin;
	TInt startQuadrant, endQuadrant;
	TBool quadrants[5];
	const TBool isEllipse = AnalyseEllipse(
		rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);

	SetupDevice();
	iDevice->DrawingBegin(&iBrushBitmap);
	CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
	if (iBrushStyle!=ENullBrush)
		{
		if (isEllipse)
			EllipseFill(rcpy);
		else
			PieFill(rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);
		}
	if (iPenStyle!=ENullPen && iPenSize.iWidth>0 && iPenSize.iHeight>0)
		PieArcOutline(rcpy,aStartradius+iOrigin,aEndradius+iOrigin,ETrue);
	if (brushRasterizer)
		{
		brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
		}
	iDevice->DrawingEnd(&iBrushBitmap);
	}

/**
Determine the pie constructed within the given rectangle.
@internalTechnology
@param rc Input - The bounding rectangle.
@param srad Input/Output - The intersection point from the geometric centre
of the ellipse to the given start point
@param erad Input/Output - The intersection point from the geometric centre
of the ellipse to the given end point
@param startq Output - The start quadrant
@param endq Output - The end quadrant
@param quads Output - Quadrants
@pre Input params rc, srad, erad are to be given.
@post Output params srad, erad, startq, endq, quads will be populated.
@return ETrue if the pie is an ellipse, otherwise EFalse.
*/
TBool CFbsBitGc::AnalyseEllipse(const TRect& rc,TPoint& srad,TPoint& erad,
							   TInt& startq,TInt& endq,TBool* quads)
	{
	startq=0;
	endq=0;
	const TPoint center = rc.Center();
	TEllipse ellipse;
	srad=ellipse.Intersection(rc,srad);
	erad=ellipse.Intersection(rc,erad);
	if (srad==erad)
		{
		quads[0]=EFalse;
		quads[1]=ETrue;
		quads[2]=ETrue;
		quads[3]=ETrue;
		quads[4]=ETrue;
		return ETrue;
		}
	const TInt startx = srad.iX - center.iX, starty = srad.iY - center.iY;
	const TInt endx = erad.iX - center.iX, endy = erad.iY - center.iY;
	if (startx>=0) startq=1;
	if (starty>=0) startq+=2;
	if (endx>=0) endq=1;
	if (endy>=0) endq+=2;
	quads[1]=EFalse,quads[2]=EFalse,quads[3]=EFalse,quads[4]=EFalse; // complete quadrants to draw
	quads[0]=EFalse; // ellipse is a sliver completely within a quadrant
	if (startq==endq)
		{
		if (startq==0 && (startx<endx || starty>endy))
			{
			quads[2]=ETrue;
			quads[3]=ETrue;
			quads[4]=ETrue;
			}
		else if (startq==1 && (startx<endx || starty<endy))
			{
			quads[1]=ETrue;
			quads[3]=ETrue;
			quads[4]=ETrue;
			}
		else if (startq==2 && (startx>endx || starty>endy))
			{
			quads[1]=ETrue;
			quads[2]=ETrue;
			quads[4]=ETrue;
			}
		else if (startq==3 && (startx>endx || starty<endy))
			{
			quads[1]=ETrue;
			quads[2]=ETrue;
			quads[3]=ETrue;
			}
		else quads[0]=ETrue; // "slice"
		}
	else
		{
		if (startq==0 && endq==1)
			{
			quads[3]=ETrue;
			quads[4]=ETrue;
			}
		else if (startq==0 && endq==3)
			quads[3]=ETrue;
		else if (startq==1 && endq==2)
			quads[1]=ETrue;
		else if (startq==1 && endq==3)
			{
			quads[1]=ETrue;
			quads[3]=ETrue;
			}
		else if (startq==2 && endq==0)
			{
			quads[2]=ETrue;
			quads[4]=ETrue;
			}
		else if (startq==2 && endq==1)
			quads[4]=ETrue;
		else if (startq==3 && endq==0)
			quads[2]=ETrue;
		else if (startq==3 && endq==2)
			{
			quads[1]=ETrue;
			quads[2]=ETrue;
			}
		}
	return EFalse;
	}

void CFbsBitGc::PieArcOutline(const TRect& ellrect,const TPoint& startradius,
							  const TPoint& endradius,TBool pie)
	{
	// arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
	TInt dotparam=iDotParam;
	TRect rcpy(ellrect);
	TPoint pt[4];
	TInt halfpenwidth=iPenSize.iWidth>>1;
	TInt halfpenheight=iPenSize.iHeight>>1;
	TInt otherhalfwidth=(iPenSize.iWidth+1)>>1;
	TInt otherhalfheight=(iPenSize.iHeight+1)>>1;
	rcpy.iTl.iX-=halfpenwidth;
	rcpy.iTl.iY-=halfpenheight;
	rcpy.iBr.iX+=otherhalfwidth;
	rcpy.iBr.iY+=otherhalfheight;
	AddRect(rcpy);
	for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
		{
		iClipRect=(*iDefaultRegionPtr)[count];
		if (!iClipRect.Intersects(rcpy))
			continue;
		iClipRect.Intersection(rcpy);
		if (UserClipRect(iClipRect)) continue;
		TArc arc;
		arc.Construct(ellrect,startradius,endradius);
		iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
		TBool dotl,dotr,dobl,dobr;
		while(!arc.SingleStep(pt[0],dotl,pt[1],dotr,pt[2],dobl,pt[3],dobr))
			{
			if (dotl) PenDrawClipped(pt[0]);
			if (dotr) PenDrawClipped(pt[1]);
			if (dobl) PenDrawClipped(pt[2]);
			if (dobr) PenDrawClipped(pt[3]);
			iDotParam+=iDotDirection;
			}
		if (pt[0].iY==pt[2].iY)
			{
			if (dotl) PenDrawClipped(pt[0]);
			if (dotr) PenDrawClipped(pt[1]);
			}
		if (pie)
			{
			TPoint temp;
			const TPoint center = ellrect.Center();
			TLinearDDA line;
			line.Construct(arc.iStart,center);
			line.SingleStep(temp);
			while(!line.SingleStep(temp))
				{
				PenDrawClipped(temp);
				iDotParam+=iDotDirection;
				}
			line.Construct(arc.iEnd,center);
			line.SingleStep(temp);
			while(!line.SingleStep(temp))
				{
				PenDrawClipped(temp);
				iDotParam+=iDotDirection;
				}
			PenDrawClipped(center);
			}
		iDevice->iDrawDevice->UpdateRegion(iClipRect);
		}
	iDotParam=dotparam;
	}

// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
void CFbsBitGc::PieFill(const TRect& ellrect, const TPoint& aStartIntersect, const TPoint& aEndIntersect,
						TInt aStartQuadrant, TInt aEndQuadrant, const TBool* aQuadrants)
	{
	// arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
	AddRect(ellrect);
	const TInt limit = iDefaultRegionPtr->Count();
	for(TInt count=0;count<limit;count++)
		{
		iClipRect=(*iDefaultRegionPtr)[count];
		if (!iClipRect.Intersects(ellrect))
			continue;
		iClipRect.Intersection(ellrect);
		if (UserClipRect(iClipRect)) continue;
		if (!aQuadrants[0])
			PieShell(ellrect, aStartIntersect, aEndIntersect, aQuadrants, aStartQuadrant, aEndQuadrant);
		else
			PieSliver(ellrect, aStartIntersect, aEndIntersect, aStartQuadrant);
		iDevice->iDrawDevice->UpdateRegion(iClipRect);
		}
	}

// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
void CFbsBitGc::PieShell(const TRect& ellrect,const TPoint& startradius,
						 const TPoint& endradius, const TBool* quads, TInt startquad, TInt endquad)
	{
	TEllipse ellipse;
	ellipse.Construct(ellrect);
	TInt c=ellrect.Center().iX;
	TPoint pt[4];
	TPoint tl,tr,bl,br;
	TBool donestart=EFalse,doneend=EFalse;
	TBool todostart=EFalse,todoend=EFalse;
	while(!ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]))
		{
		if (pt[startquad].iY==startradius.iY)
			todostart=ETrue;
		if (pt[endquad].iY==endradius.iY)
			todoend=ETrue;
		pt[0].iX++;
		pt[1].iX--;
		pt[2].iX++;
		pt[3].iX--;
		tl.iY=pt[0].iY;
		tr.iY=pt[1].iY;
		bl.iY=pt[2].iY;
		br.iY=pt[3].iY;
		if (quads[1] || (endquad==0 && !doneend)) // tl quadrant, half top end chord
			tl.iX=pt[0].iX;
		else tl.iX=c+1;
		if (quads[2] || (startquad==1 && !donestart)) // tr quadrant, half top start chord
			tr.iX=pt[1].iX;
		else tr.iX=c;
		if (quads[3] || (startquad==2 && !donestart)) // bl quadrant, half top start chord
			bl.iX=pt[2].iX;
		else bl.iX=c+1;
		if (quads[4] || (endquad==3 && !doneend)) // br quadrant, half top end chord
			br.iX=pt[3].iX;
		else br.iX=c;
		ClipFillLine(tl,tr);
		ClipFillLine(bl,br);
		// do partial quadrants
		if (todostart)
			{
			if (startquad==0)
				{
				tl.iX=pt[0].iX;
				tr.iX=startradius.iX;
				ClipFillLine(tl,tr);
				}
			else if (startquad==3)
				{
				bl.iX=startradius.iX;
				br.iX=pt[3].iX;
				ClipFillLine(bl,br);
				}
			}
		if (todoend)
			{
			if (endquad==2)
				{
				bl.iX=pt[2].iX;
				br.iX=endradius.iX;
				ClipFillLine(bl,br);
				}
			else if (endquad==1)
				{
				tl.iX=endradius.iX;
				tr.iX=pt[1].iX;
				ClipFillLine(tl,tr);
				}
			}
		donestart=todostart;
		doneend=todoend;
		}
	tl.iX=c+1;
	tr.iX=c;
	if (pt[0].iY==pt[2].iY) // congruent mid lines
		{
		if (pt[startquad].iY==startradius.iY)
			todostart=ETrue;
		if (pt[endquad].iY==endradius.iY)
			todoend=ETrue;
		pt[0].iX++;
		pt[1].iX--;
		tl.iY=pt[0].iY;
		tr.iY=tl.iY;
		TBool leftflag=EFalse,rightflag=EFalse;
		if (quads[1] || (endquad==0 && !doneend) ||
			quads[3] || (startquad==2 && !donestart) ||
			(todostart && startquad==0) || (todoend && endquad==2))
			leftflag=ETrue;
		if (quads[2] || (startquad==1 && !donestart) ||
			quads[4] || (endquad==3 && !doneend) ||
			(todostart && startquad==3) || (todoend && endquad==1))
			rightflag=ETrue;
		if (leftflag) tl.iX=pt[0].iX;
		if (rightflag) tr.iX=pt[1].iX;
		ClipFillLine(tl,tr);
		}
	else
		{
		tl.iY=ellrect.Center().iY;
		tr.iY=tl.iY;
		if (startquad==3) tr.iX=startradius.iX-1;
		if (endquad==2) tl.iX=endradius.iX+1;
		ClipFillLine(tl,tr);
		}
	PieTriangles(startquad==1 || startquad==2,startradius,ellrect.Center());
	PieTriangles(endquad==0 || endquad==3,endradius,ellrect.Center());
	}

// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
void CFbsBitGc::PieTriangles(TBool aInside,const TPoint& aStart,const TPoint& aEnd)
	{
	TInt x=aInside?aEnd.iX:aStart.iX;
	if (aStart.iX>aEnd.iX)
		{
		if (aInside)
			x++;
		else
			x--;
		}
	else
		if (!aInside)
			x++;
	TLinearDDA line;
	TPoint pt,left,right;
	line.Construct(aStart,aEnd);
	line.NextStep(pt);
	while(!line.NextStep(pt))
		{
		if (pt.iY==aEnd.iY) break;
		left.iX=Min(pt.iX,x);
		right.iX=Max(pt.iX,x);
		left.iY=right.iY=pt.iY;
		ClipFillLine(left,right);
		}
	}

// if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
void CFbsBitGc::PieSliver(const TRect& ellrect,const TPoint& startradius,
						  const TPoint& endradius,TInt quad)
	{
	TPoint center=ellrect.Center(),left,right;
	TPoint nearinter(startradius),farinter(endradius);
	if (Abs(nearinter.iY-center.iY)>Abs(farinter.iY-center.iY))
		{
		nearinter=endradius;
		farinter=startradius;
		}
	TBool ellipseComplete = EFalse;
	TPoint pt[4];
	TEllipse ellipse;
	ellipse.Construct(ellrect);
	TLinearDDA mainline;
	mainline.Construct(farinter,center);
	ellipseComplete = ellipse.SingleStep(pt[0],pt[1],pt[2],pt[3]);
	mainline.SingleStep(right);
	do	{
		while(!ellipseComplete && pt[quad].iY!=right.iY)
			ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
		left=pt[quad];
		while(!ellipseComplete && pt[quad].iY==right.iY)
			{
			left=pt[quad];
			ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
			}
		if (right.iY==nearinter.iY || (ellipseComplete && (pt[0].iY != pt[2].iY)))
			break;
		if (left.iX>right.iX)
			{
			TInt temp=left.iX;
			left.iX=right.iX;
			right.iX=temp;
			}
		if(right==farinter && left.iX<=right.iX)
			{
			continue;
			}
		left.iX++;
		right.iX--;
		if (left.iX<=right.iX)
			ClipFillLine(left,right);
		}
	while(!mainline.NextStep(right));
	TPoint temppt;
	TLinearDDA line;
	line.Construct(nearinter,center);
	TBool linestat=EFalse;
	do
		linestat=line.SingleStep(temppt);
	while(temppt.iY!=right.iY && !linestat);
	do	{
		do	{
			left=temppt;
			linestat=line.SingleStep(temppt);
			}
		while(temppt.iY==right.iY && !linestat);
		if (ellipseComplete)
			break;
		if (left.iX>right.iX)
			{
			TInt temp=left.iX;
			left.iX=right.iX;
			right.iX=temp;
			}
		if(right==farinter && left.iX<=right.iX)
			{
			continue;
			}
		left.iX++;
		right.iX--;
		if (left.iX<=right.iX)
			ClipFillLine(left,right);
		}
	while(!mainline.NextStep(right));
	}