author | Gareth Stockwell <gareth.stockwell@accenture.com> |
Fri, 22 Oct 2010 11:38:29 +0100 | |
branch | bug235_bringup_0 |
changeset 206 | c170e304623f |
parent 0 | 5d03bc08d59c |
permissions | -rw-r--r-- |
// 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)); }