graphicsdeviceinterface/bitgdi/sbit/PIEARC.CPP
author William Roberts <williamr@symbian.org>
Thu, 03 Jun 2010 17:39:46 +0100
branchNewGraphicsArchitecture
changeset 87 0709f76d91e5
parent 0 5d03bc08d59c
permissions -rw-r--r--
Add MMP files to build libOpenVG_sw.lib which uses LINKAS to redirect to libOpenVG.dll (and the same for libEGL_sw.lib and libOpenVGU_sw.lib). Only the libEGL_sw.lib redirection isn't activated - this can't happen until there is a merged libEGL.dll which supports the OpenWF synchronisation and also implements the graphical support functions. The overall aim is to eliminate the *_sw.dll implementations, at least as a compile-time way of choosing a software-only implementation.The correct way to choose is to put the right set of libraries into a ROM with suitable renaming, and in the emulator to use the "switching DLL" technique to pick the right set. As the Symbian Foundation doesn't have any alternative implementations, we don't need the switching DLLs and we can build directly to the correct name.

// 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));
	}