diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/bitgdi/sbit/PIEARC.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicsdeviceinterface/bitgdi/sbit/PIEARC.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,750 @@ +// 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 +#include +#include "BITPANIC.H" +#include +#include + +// 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.iXiEnd.iY)) + { + iTrquad=ETrue; + iBlquad=ETrue; + iBrquad=ETrue; + iSlice=EFalse; + } + else if (iStartquad==1 && (iStart.iXiEnd.iX || iStart.iY>iEnd.iY)) + { + iTlquad=ETrue; + iTrquad=ETrue; + iBrquad=ETrue; + iSlice=EFalse; + } + else if (iStartquad==3 && (iStart.iX>iEnd.iX || iStart.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.iXiEnd.iY)) + { + iEndquadenabled=EFalse; + iEndquaddone=ETrue; + } + if (iEndquad==3 && (aBottomRight.iX>iEnd.iX || aBottomRight.iY=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 CGraphicsContext::DrawArc(). 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 CGraphicsContext::DrawPie(). 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 && (startxendy)) + { + quads[2]=ETrue; + quads[3]=ETrue; + quads[4]=ETrue; + } + else if (startq==1 && (startxendx || starty>endy)) + { + quads[1]=ETrue; + quads[2]=ETrue; + quads[4]=ETrue; + } + else if (startq==3 && (startx>endx || starty>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;countCount();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;countiDrawDevice->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)); + } +