os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdipiearc.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdipiearc.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,815 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "swdirectgdiengine.h"
1.20 +#include "swdirectgdiellipse.h"
1.21 +
1.22 +
1.23 +/**
1.24 +A utility class to efficiently draw arcs.
1.25 +@see CSwDirectGdiEngine::PieArcOutline
1.26 +
1.27 +@internalComponent
1.28 +*/
1.29 +class TSwDirectGdiArc : public TSwDirectGdiEllipse
1.30 + {
1.31 +public:
1.32 + void Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd);
1.33 + TBool SingleStep(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
1.34 + void Step(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
1.35 +public:
1.36 + TPoint iStart;
1.37 + TPoint iEnd;
1.38 +private:
1.39 + TBool iTlquad;
1.40 + TBool iTrquad;
1.41 + TBool iBlquad;
1.42 + TBool iBrquad;
1.43 + TBool iStartquadenabled;
1.44 + TBool iEndquadenabled;
1.45 + TBool iStartquaddone;
1.46 + TBool iEndquaddone;
1.47 + TInt iStartquad;
1.48 + TInt iEndquad;
1.49 + TBool iSlice;
1.50 + };
1.51 +
1.52 +/**
1.53 +Constructs a TSwDirectGdiArc.
1.54 +@param aRect The bounding rectangle.
1.55 +@param aStart The arc start point.
1.56 +@param aEnd The arc end point.
1.57 +@see CSwDirectGdiEngine::PieArcOutline
1.58 +*/
1.59 +void TSwDirectGdiArc::Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd)
1.60 + {
1.61 + iStart=Intersection(aRect,aStart);
1.62 + iEnd=Intersection(aRect,aEnd);
1.63 + TSwDirectGdiEllipse::Construct(aRect);
1.64 + iTlquad=EFalse;
1.65 + iTrquad=EFalse;
1.66 + iBlquad=EFalse;
1.67 + iBrquad=EFalse;
1.68 + iStartquadenabled=EFalse;
1.69 + iEndquadenabled=EFalse;
1.70 + iSlice=EFalse;
1.71 + iStartquad=0;
1.72 + iEndquad=0;
1.73 + TPoint center=aRect.Center();
1.74 + if (iStart.iX>=center.iX) iStartquad=1;
1.75 + if (iStart.iY>=center.iY) iStartquad+=2;
1.76 + if (iEnd.iX>=center.iX) iEndquad=1;
1.77 + if (iEnd.iY>=center.iY) iEndquad+=2;
1.78 + if (iStartquad!=iEndquad)
1.79 + {
1.80 + if (iStartquad==0 && iEndquad==1)
1.81 + {
1.82 + iBlquad=ETrue;
1.83 + iBrquad=ETrue;
1.84 + }
1.85 + else if (iStartquad==0 && iEndquad==3)
1.86 + iBlquad=ETrue;
1.87 + else if (iStartquad==1 && iEndquad==2)
1.88 + iTlquad=ETrue;
1.89 + else if (iStartquad==1 && iEndquad==3)
1.90 + {
1.91 + iTlquad=ETrue;
1.92 + iBlquad=ETrue;
1.93 + }
1.94 + else if (iStartquad==2 && iEndquad==0)
1.95 + {
1.96 + iTrquad=ETrue;
1.97 + iBrquad=ETrue;
1.98 + }
1.99 + else if (iStartquad==2 && iEndquad==1)
1.100 + iBrquad=ETrue;
1.101 + else if (iStartquad==3 && iEndquad==0)
1.102 + iTrquad=ETrue;
1.103 + else if (iStartquad==3 && iEndquad==2)
1.104 + {
1.105 + iTlquad=ETrue;
1.106 + iTrquad=ETrue;
1.107 + }
1.108 + }
1.109 + else if (iStart==iEnd)
1.110 + {
1.111 + iTlquad=ETrue;
1.112 + iTrquad=ETrue;
1.113 + iBlquad=ETrue;
1.114 + iBrquad=ETrue;
1.115 + }
1.116 + else
1.117 + {
1.118 + iSlice=ETrue;
1.119 + if (iStartquad==0 && (iStart.iX<iEnd.iX || iStart.iY>iEnd.iY))
1.120 + {
1.121 + iTrquad=ETrue;
1.122 + iBlquad=ETrue;
1.123 + iBrquad=ETrue;
1.124 + iSlice=EFalse;
1.125 + }
1.126 + else if (iStartquad==1 && (iStart.iX<iEnd.iX || iStart.iY<iEnd.iY))
1.127 + {
1.128 + iTlquad=ETrue;
1.129 + iBlquad=ETrue;
1.130 + iBrquad=ETrue;
1.131 + iSlice=EFalse;
1.132 + }
1.133 + else if (iStartquad==2 && (iStart.iX>iEnd.iX || iStart.iY>iEnd.iY))
1.134 + {
1.135 + iTlquad=ETrue;
1.136 + iTrquad=ETrue;
1.137 + iBrquad=ETrue;
1.138 + iSlice=EFalse;
1.139 + }
1.140 + else if (iStartquad==3 && (iStart.iX>iEnd.iX || iStart.iY<iEnd.iY))
1.141 + {
1.142 + iTlquad=ETrue;
1.143 + iTrquad=ETrue;
1.144 + iBlquad=ETrue;
1.145 + iSlice=EFalse;
1.146 + }
1.147 + }
1.148 + if (iStartquad==1 || iStartquad==2)
1.149 + iStartquadenabled=ETrue;
1.150 + if (iEndquad==0 || iEndquad==3)
1.151 + iEndquadenabled=ETrue;
1.152 + iStartquaddone=EFalse;
1.153 + iEndquaddone=EFalse;
1.154 + }
1.155 +
1.156 +/**
1.157 +Produces the next stage creating an arc, taking four points (the corners of
1.158 +the rectangle the arc should fill) as parameters.
1.159 +
1.160 +@param aTopLeft Top left corner of rectangle.
1.161 +@param aDoTl Span the top left quadrant.
1.162 +@param aTopRight Top right corner of rectangle.
1.163 +@param aDoTr Span the top right quadrant.
1.164 +@param aBottomLeft Bottom left corner of rectangle.
1.165 +@param aDoBl Span the bottom left quadrant.
1.166 +@param aBottomRight Bottom right corner of rectangle.
1.167 +@param aDoBr Span the bottom right quadrant.
1.168 +@return TBool ETrue if step completed successfully.
1.169 +@see TSwDirectGdiEllipse::SingleStep
1.170 +*/
1.171 +TBool TSwDirectGdiArc::SingleStep(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,
1.172 + TBool& aDoTr,TPoint& aBottomLeft,TBool& aDoBl,
1.173 + TPoint& aBottomRight,TBool& aDoBr)
1.174 + {
1.175 + TBool finished=TSwDirectGdiEllipse::SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
1.176 + Step(aTopLeft,aDoTl,aTopRight,aDoTr,aBottomLeft,aDoBl,aBottomRight,aDoBr);
1.177 +
1.178 + return finished;
1.179 + }
1.180 +
1.181 +/**
1.182 +Determines how many quadrants are left to draw.
1.183 +
1.184 +@param aTopLeft Top left corner of rectangle.
1.185 +@param aDoTl Span the top left quadrant.
1.186 +@param aTopRight Top right corner of rectangle.
1.187 +@param aDoTr Span the top right quadrant.
1.188 +@param aBottomLeft Bottom left corner of rectangle.
1.189 +@param aDoBl Span the bottom left quadrant.
1.190 +@param aBottomRight Bottom right corner of rectangle.
1.191 +@param aDoBr Span the bottom right quadrant.
1.192 +@see TSwDirectGdiArc::SingleStep
1.193 +@see TSwDirectGdiArc::Construct
1.194 +*/
1.195 +void TSwDirectGdiArc::Step(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,TBool& aDoTr,
1.196 + TPoint& aBottomLeft,TBool& aDoBl,TPoint& aBottomRight,TBool& aDoBr)
1.197 + {
1.198 + aDoTl=iTlquad;
1.199 + aDoTr=iTrquad;
1.200 + aDoBl=iBlquad;
1.201 + aDoBr=iBrquad;
1.202 + if (!iStartquaddone)
1.203 + {
1.204 + if (!iStartquadenabled)
1.205 + {
1.206 + if (iStartquad==0 && aTopLeft.iX<=iStart.iX && aTopLeft.iY>=iStart.iY)
1.207 + {
1.208 + iStartquadenabled=ETrue;
1.209 + iStartquaddone=ETrue;
1.210 + }
1.211 + if (iStartquad==3 && aBottomRight.iX>=iStart.iX && aBottomRight.iY<=iStart.iY)
1.212 + {
1.213 + iStartquadenabled=ETrue;
1.214 + iStartquaddone=ETrue;
1.215 + }
1.216 + }
1.217 + else
1.218 + {
1.219 + if (iStartquad==1 && (aTopRight.iX>iStart.iX || aTopRight.iY>iStart.iY))
1.220 + {
1.221 + iStartquadenabled=EFalse;
1.222 + iStartquaddone=ETrue;
1.223 + }
1.224 + if (iStartquad==2 && (aBottomLeft.iX<iStart.iX || aBottomLeft.iY<iStart.iY))
1.225 + {
1.226 + iStartquadenabled=EFalse;
1.227 + iStartquaddone=ETrue;
1.228 + }
1.229 + }
1.230 + }
1.231 + if (!iEndquaddone)
1.232 + {
1.233 + if (iEndquadenabled)
1.234 + {
1.235 + if (iEndquad==0 && (aTopLeft.iX<iEnd.iX || aTopLeft.iY>iEnd.iY))
1.236 + {
1.237 + iEndquadenabled=EFalse;
1.238 + iEndquaddone=ETrue;
1.239 + }
1.240 + if (iEndquad==3 && (aBottomRight.iX>iEnd.iX || aBottomRight.iY<iEnd.iY))
1.241 + {
1.242 + iEndquadenabled=EFalse;
1.243 + iEndquaddone=ETrue;
1.244 + }
1.245 + }
1.246 + else
1.247 + {
1.248 + if (iEndquad==1 && aTopRight.iX>=iEnd.iX && aTopRight.iY>=iEnd.iY)
1.249 + {
1.250 + iEndquadenabled=ETrue;
1.251 + iEndquaddone=ETrue;
1.252 + }
1.253 + if (iEndquad==2 && aBottomLeft.iX<=iEnd.iX && aBottomLeft.iY<=iEnd.iY)
1.254 + {
1.255 + iEndquadenabled=ETrue;
1.256 + iEndquaddone=ETrue;
1.257 + }
1.258 + }
1.259 + }
1.260 + if (iStartquad!=iEndquad)
1.261 + {
1.262 + if (iStartquadenabled)
1.263 + {
1.264 + if (iStartquad==0) aDoTl=ETrue;
1.265 + else if (iStartquad==1) aDoTr=ETrue;
1.266 + else if (iStartquad==2) aDoBl=ETrue;
1.267 + else if (iStartquad==3) aDoBr=ETrue;
1.268 + }
1.269 + if (iEndquadenabled)
1.270 + {
1.271 + if (iEndquad==0) aDoTl=ETrue;
1.272 + else if (iEndquad==1) aDoTr=ETrue;
1.273 + else if (iEndquad==2) aDoBl=ETrue;
1.274 + else if (iEndquad==3) aDoBr=ETrue;
1.275 + }
1.276 + }
1.277 + else
1.278 + {
1.279 + if (iSlice)
1.280 + {
1.281 + if (iStartquadenabled && iEndquadenabled)
1.282 + {
1.283 + if (iStartquad==0) aDoTl=ETrue;
1.284 + else if (iStartquad==1) aDoTr=ETrue;
1.285 + else if (iStartquad==2) aDoBl=ETrue;
1.286 + else if (iStartquad==3) aDoBr=ETrue;
1.287 + }
1.288 + }
1.289 + else
1.290 + {
1.291 + if (iStartquadenabled || iEndquadenabled)
1.292 + {
1.293 + if (iStartquad==0) aDoTl=ETrue;
1.294 + else if (iStartquad==1) aDoTr=ETrue;
1.295 + else if (iStartquad==2) aDoBl=ETrue;
1.296 + else if (iStartquad==3) aDoBr=ETrue;
1.297 + }
1.298 + }
1.299 + }
1.300 + if (aTopLeft.iX==aTopRight.iX)
1.301 + {
1.302 + if (aDoTl && aDoTr) aDoTr=EFalse;
1.303 + if (aDoBl && aDoBr) aDoBr=EFalse;
1.304 + }
1.305 + }
1.306 +
1.307 +//
1.308 +// Pie and Arc drawing functions
1.309 +//
1.310 +
1.311 +/**
1.312 +@see MDirectGdiEngine::DrawArc()
1.313 +*/
1.314 +void CSwDirectGdiEngine::DrawArc(const TRect& aRect,const TPoint& aStart,
1.315 + const TPoint& aEnd)
1.316 + {
1.317 + TRect rcpy(aRect);
1.318 + rcpy.Move(iOrigin);
1.319 + TruncateRect(rcpy);
1.320 + TRect targetRect(rcpy);
1.321 + targetRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
1.322 + PieArcOutline(rcpy,aStart+iOrigin,aEnd+iOrigin,EFalse);
1.323 + }
1.324 +
1.325 +/**
1.326 +@see MDirectGdiEngine::DrawPie()
1.327 +*/
1.328 +void CSwDirectGdiEngine::DrawPie(const TRect& aRect,const TPoint& aStart,
1.329 + const TPoint& aEnd)
1.330 + {
1.331 + TRect rcpy(aRect);
1.332 + rcpy.Move(iOrigin);
1.333 + TruncateRect(rcpy);
1.334 + TPoint startIntersect = aStart + iOrigin, endIntersect = aEnd + iOrigin;
1.335 + TInt startQuadrant, endQuadrant;
1.336 + TBool quadrants[5];
1.337 + const TBool isEllipse = AnalyseEllipse(
1.338 + rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);
1.339 +
1.340 + if (iBrushStyle!=DirectGdi::ENullBrush)
1.341 + {
1.342 + if (isEllipse)
1.343 + EllipseFill(rcpy);
1.344 + else
1.345 + PieFill(rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);
1.346 + }
1.347 + if ((iPenStyle!=DirectGdi::ENullPen) && (iPenSize.iWidth>0) && (iPenSize.iHeight>0))
1.348 + PieArcOutline(rcpy,aStart+iOrigin,aEnd+iOrigin,ETrue);
1.349 + }
1.350 +
1.351 +/**
1.352 +Calculates which quadrants are completely filled and which quadrants contain the
1.353 +start and end points.
1.354 +
1.355 +@param aRect The bounding rectangle.
1.356 +@param aStart The arc start point.
1.357 +@param aEnd The arc end point.
1.358 +@param aStartQuad On return, contains the quadrant which contains aStart.
1.359 +@param aEndQuad On return, contains the quadrant which contains aEnd.
1.360 +@param aQuads On return, populates an array of full quadrants to fill.
1.361 +@pre Input params aRect, aStart, aEnd are to be given.
1.362 +@post Output params aStart, aEnd, aStartQuad, aEndQuad, aQuads will be populated.
1.363 +@return ETrue if the pie is an ellipse, otherwise EFalse.
1.364 +*/
1.365 +TBool CSwDirectGdiEngine::AnalyseEllipse(const TRect& aRect,TPoint& aStart,TPoint& aEnd,
1.366 + TInt& aStartQuad,TInt& aEndQuad,TBool* aQuads)
1.367 + {
1.368 + aStartQuad=0;
1.369 + aEndQuad=0;
1.370 + const TPoint center = aRect.Center();
1.371 + TSwDirectGdiEllipse ellipse;
1.372 + aStart=ellipse.Intersection(aRect,aStart);
1.373 + aEnd=ellipse.Intersection(aRect,aEnd);
1.374 + if (aStart==aEnd)
1.375 + {
1.376 + aQuads[0]=EFalse;
1.377 + aQuads[1]=ETrue;
1.378 + aQuads[2]=ETrue;
1.379 + aQuads[3]=ETrue;
1.380 + aQuads[4]=ETrue;
1.381 + return ETrue;
1.382 + }
1.383 + const TInt startx = aStart.iX - center.iX, starty = aStart.iY - center.iY;
1.384 + const TInt endx = aEnd.iX - center.iX, endy = aEnd.iY - center.iY;
1.385 + if (startx>=0) aStartQuad=1;
1.386 + if (starty>=0) aStartQuad+=2;
1.387 + if (endx>=0) aEndQuad=1;
1.388 + if (endy>=0) aEndQuad+=2;
1.389 + aQuads[1]=EFalse,aQuads[2]=EFalse,aQuads[3]=EFalse,aQuads[4]=EFalse; // complete quadrants to draw
1.390 + aQuads[0]=EFalse; // ellipse is a sliver completely within a quadrant
1.391 + if (aStartQuad==aEndQuad)
1.392 + {
1.393 + if (aStartQuad==0 && (startx<endx || starty>endy))
1.394 + {
1.395 + aQuads[2]=ETrue;
1.396 + aQuads[3]=ETrue;
1.397 + aQuads[4]=ETrue;
1.398 + }
1.399 + else if (aStartQuad==1 && (startx<endx || starty<endy))
1.400 + {
1.401 + aQuads[1]=ETrue;
1.402 + aQuads[3]=ETrue;
1.403 + aQuads[4]=ETrue;
1.404 + }
1.405 + else if (aStartQuad==2 && (startx>endx || starty>endy))
1.406 + {
1.407 + aQuads[1]=ETrue;
1.408 + aQuads[2]=ETrue;
1.409 + aQuads[4]=ETrue;
1.410 + }
1.411 + else if (aStartQuad==3 && (startx>endx || starty<endy))
1.412 + {
1.413 + aQuads[1]=ETrue;
1.414 + aQuads[2]=ETrue;
1.415 + aQuads[3]=ETrue;
1.416 + }
1.417 + else aQuads[0]=ETrue; // "slice"
1.418 + }
1.419 + else
1.420 + {
1.421 + if (aStartQuad==0 && aEndQuad==1)
1.422 + {
1.423 + aQuads[3]=ETrue;
1.424 + aQuads[4]=ETrue;
1.425 + }
1.426 + else if (aStartQuad==0 && aEndQuad==3)
1.427 + aQuads[3]=ETrue;
1.428 + else if (aStartQuad==1 && aEndQuad==2)
1.429 + aQuads[1]=ETrue;
1.430 + else if (aStartQuad==1 && aEndQuad==3)
1.431 + {
1.432 + aQuads[1]=ETrue;
1.433 + aQuads[3]=ETrue;
1.434 + }
1.435 + else if (aStartQuad==2 && aEndQuad==0)
1.436 + {
1.437 + aQuads[2]=ETrue;
1.438 + aQuads[4]=ETrue;
1.439 + }
1.440 + else if (aStartQuad==2 && aEndQuad==1)
1.441 + aQuads[4]=ETrue;
1.442 + else if (aStartQuad==3 && aEndQuad==0)
1.443 + aQuads[2]=ETrue;
1.444 + else if (aStartQuad==3 && aEndQuad==2)
1.445 + {
1.446 + aQuads[1]=ETrue;
1.447 + aQuads[2]=ETrue;
1.448 + }
1.449 + }
1.450 + return EFalse;
1.451 + }
1.452 +
1.453 +/**
1.454 +Draws the outline of a pie or arc.
1.455 +
1.456 +@param aRect The bounding rectangle.
1.457 +@param aStart The arc start point.
1.458 +@param aEnd The arc end point.
1.459 +@param aPie If this is the outline for a pie ETrue, else EFalse
1.460 +*/
1.461 +void CSwDirectGdiEngine::PieArcOutline(const TRect& aRect,const TPoint& aStart,
1.462 + const TPoint& aEnd,TBool aPie)
1.463 + {
1.464 + // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
1.465 + TInt dotparam=iDotParam;
1.466 + TRect rcpy(aRect);
1.467 + TPoint pt[4];
1.468 + TInt halfpenwidth=iPenSize.iWidth>>1;
1.469 + TInt halfpenheight=iPenSize.iHeight>>1;
1.470 + TInt otherhalfwidth=(iPenSize.iWidth+1)>>1;
1.471 + TInt otherhalfheight=(iPenSize.iHeight+1)>>1;
1.472 + rcpy.iTl.iX-=halfpenwidth;
1.473 + rcpy.iTl.iY-=halfpenheight;
1.474 + rcpy.iBr.iX+=otherhalfwidth;
1.475 + rcpy.iBr.iY+=otherhalfheight;
1.476 + TRect clipRect(0,0,0,0);
1.477 + for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
1.478 + {
1.479 + clipRect=(*iDefaultRegionPtr)[count];
1.480 + if (!clipRect.Intersects(rcpy))
1.481 + continue;
1.482 + clipRect.Intersection(rcpy);
1.483 + TSwDirectGdiArc arc;
1.484 + arc.Construct(aRect,aStart,aEnd);
1.485 + iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
1.486 + TBool dotl,dotr,dobl,dobr;
1.487 + while(!arc.SingleStep(pt[0],dotl,pt[1],dotr,pt[2],dobl,pt[3],dobr))
1.488 + {
1.489 + if (dotl) PenDrawClipped(pt[0], clipRect);
1.490 + if (dotr) PenDrawClipped(pt[1], clipRect);
1.491 + if (dobl) PenDrawClipped(pt[2], clipRect);
1.492 + if (dobr) PenDrawClipped(pt[3], clipRect);
1.493 + iDotParam+=iDotDirection;
1.494 + }
1.495 + if (pt[0].iY==pt[2].iY)
1.496 + {
1.497 + if (dotl) PenDrawClipped(pt[0], clipRect);
1.498 + if (dotr) PenDrawClipped(pt[1], clipRect);
1.499 + }
1.500 + if (aPie)
1.501 + {
1.502 + TPoint temp;
1.503 + const TPoint center = aRect.Center();
1.504 + TLinearDDA line;
1.505 + line.Construct(arc.iStart,center);
1.506 + line.SingleStep(temp);
1.507 + while(!line.SingleStep(temp))
1.508 + {
1.509 + PenDrawClipped(temp, clipRect);
1.510 + iDotParam+=iDotDirection;
1.511 + }
1.512 + line.Construct(arc.iEnd,center);
1.513 + line.SingleStep(temp);
1.514 + while(!line.SingleStep(temp))
1.515 + {
1.516 + PenDrawClipped(temp, clipRect);
1.517 + iDotParam+=iDotDirection;
1.518 + }
1.519 + PenDrawClipped(center, clipRect);
1.520 + }
1.521 + iDrawDevice->UpdateRegion(clipRect);
1.522 + }
1.523 + iDotParam=dotparam;
1.524 + }
1.525 +
1.526 +/**
1.527 +Fills a pie.
1.528 +
1.529 +@param aRect The bounding rectangle.
1.530 +@param aStart The arc start point.
1.531 +@param aEnd The arc end point.
1.532 +@param aStartQuad The quadrant which contains aStart.
1.533 +@param aEndQuad The quadrant which contains aEnd.
1.534 +@param aQuads An array of full quadrants to fill.
1.535 +@see CSwDirectGdiEngine::DrawPie
1.536 +@see CSwDirectGdiEngine::AnalyseEllipse
1.537 +*/
1.538 +void CSwDirectGdiEngine::PieFill(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd,
1.539 + TInt aStartQuad, TInt aEndQuad, const TBool* aQuads)
1.540 + {
1.541 + // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
1.542 + const TInt limit = iDefaultRegionPtr->Count();
1.543 + TRect clipRect(0,0,0,0);
1.544 + for(TInt count=0;count<limit;count++)
1.545 + {
1.546 + clipRect=(*iDefaultRegionPtr)[count];
1.547 + if (!clipRect.Intersects(aRect))
1.548 + {
1.549 + continue;
1.550 + }
1.551 + clipRect.Intersection(aRect);
1.552 + if (!aQuads[0])
1.553 + {
1.554 + PieShell(aRect, aStart, aEnd, aQuads, aStartQuad, aEndQuad, clipRect);
1.555 + }
1.556 + else
1.557 + {
1.558 + PieSliver(aRect, aStart, aEnd, aStartQuad, clipRect);
1.559 + }
1.560 + iDrawDevice->UpdateRegion(clipRect);
1.561 + }
1.562 + }
1.563 +
1.564 +/**
1.565 +Draws a pie spanning one or more quadrants.
1.566 +
1.567 +@param aRect The bounding rectangle.
1.568 +@param aStart The arc start point.
1.569 +@param aEnd The arc end point.
1.570 +@param aQuads Array of full quadrants to fill.
1.571 +@param aStartQuad The quadrant which contains aStart.
1.572 +@param aEndQuad The quadrant which contains aEnd.
1.573 +@param aClipRect The rectangle to which the pie is clipped.
1.574 +*/
1.575 +void CSwDirectGdiEngine::PieShell(const TRect& aRect,const TPoint& aStart,
1.576 + const TPoint& aEnd, const TBool* aQuads, TInt aStartQuad,
1.577 + TInt aEndQuad, TRect aClipRect)
1.578 + {
1.579 + TSwDirectGdiEllipse ellipse;
1.580 + ellipse.Construct(aRect);
1.581 + TInt c=aRect.Center().iX;
1.582 + TPoint pt[4];
1.583 + TPoint tl,tr,bl,br;
1.584 + TBool donestart=EFalse;
1.585 + TBool doneend=EFalse;
1.586 + TBool todostart=EFalse;
1.587 + TBool todoend=EFalse;
1.588 + while(!ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]))
1.589 + {
1.590 + if (pt[aStartQuad].iY==aStart.iY)
1.591 + todostart=ETrue;
1.592 + if (pt[aEndQuad].iY==aEnd.iY)
1.593 + todoend=ETrue;
1.594 + pt[0].iX++;
1.595 + pt[1].iX--;
1.596 + pt[2].iX++;
1.597 + pt[3].iX--;
1.598 + tl.iY=pt[0].iY;
1.599 + tr.iY=pt[1].iY;
1.600 + bl.iY=pt[2].iY;
1.601 + br.iY=pt[3].iY;
1.602 + if (aQuads[1] || (aEndQuad==0 && !doneend)) // tl quadrant, half top end chord
1.603 + tl.iX=pt[0].iX;
1.604 + else tl.iX=c+1;
1.605 + if (aQuads[2] || (aStartQuad==1 && !donestart)) // tr quadrant, half top start chord
1.606 + tr.iX=pt[1].iX;
1.607 + else tr.iX=c;
1.608 + if (aQuads[3] || (aStartQuad==2 && !donestart)) // bl quadrant, half top start chord
1.609 + bl.iX=pt[2].iX;
1.610 + else bl.iX=c+1;
1.611 + if (aQuads[4] || (aEndQuad==3 && !doneend)) // br quadrant, half top end chord
1.612 + br.iX=pt[3].iX;
1.613 + else br.iX=c;
1.614 + ClipFillLine(tl,tr,aClipRect);
1.615 + ClipFillLine(bl,br,aClipRect);
1.616 + // do partial quadrants
1.617 + if (todostart)
1.618 + {
1.619 + if (aStartQuad==0)
1.620 + {
1.621 + tl.iX=pt[0].iX;
1.622 + tr.iX=aStart.iX;
1.623 + ClipFillLine(tl,tr,aClipRect);
1.624 + }
1.625 + else if (aStartQuad==3)
1.626 + {
1.627 + bl.iX=aStart.iX;
1.628 + br.iX=pt[3].iX;
1.629 + ClipFillLine(bl,br,aClipRect);
1.630 + }
1.631 + }
1.632 + if (todoend)
1.633 + {
1.634 + if (aEndQuad==2)
1.635 + {
1.636 + bl.iX=pt[2].iX;
1.637 + br.iX=aEnd.iX;
1.638 + ClipFillLine(bl,br,aClipRect);
1.639 + }
1.640 + else if (aEndQuad==1)
1.641 + {
1.642 + tl.iX=aEnd.iX;
1.643 + tr.iX=pt[1].iX;
1.644 + ClipFillLine(tl,tr,aClipRect);
1.645 + }
1.646 + }
1.647 + donestart=todostart;
1.648 + doneend=todoend;
1.649 + }
1.650 + tl.iX=c+1;
1.651 + tr.iX=c;
1.652 + if (pt[0].iY==pt[2].iY) // congruent mid lines
1.653 + {
1.654 + if (pt[aStartQuad].iY==aStart.iY)
1.655 + todostart=ETrue;
1.656 + if (pt[aEndQuad].iY==aEnd.iY)
1.657 + todoend=ETrue;
1.658 + pt[0].iX++;
1.659 + pt[1].iX--;
1.660 + tl.iY=pt[0].iY;
1.661 + tr.iY=tl.iY;
1.662 + TBool leftflag=EFalse;
1.663 + TBool rightflag=EFalse;
1.664 + if (aQuads[1] || (aEndQuad==0 && !doneend) ||
1.665 + aQuads[3] || (aStartQuad==2 && !donestart) ||
1.666 + (todostart && aStartQuad==0) || (todoend && aEndQuad==2))
1.667 + leftflag=ETrue;
1.668 + if (aQuads[2] || (aStartQuad==1 && !donestart) ||
1.669 + aQuads[4] || (aEndQuad==3 && !doneend) ||
1.670 + (todostart && aStartQuad==3) || (todoend && aEndQuad==1))
1.671 + rightflag=ETrue;
1.672 + if (leftflag) tl.iX=pt[0].iX;
1.673 + if (rightflag) tr.iX=pt[1].iX;
1.674 + ClipFillLine(tl,tr,aClipRect);
1.675 + }
1.676 + else
1.677 + {
1.678 + tl.iY=aRect.Center().iY;
1.679 + tr.iY=tl.iY;
1.680 + if (aStartQuad==3) tr.iX=aStart.iX-1;
1.681 + if (aEndQuad==2) tl.iX=aEnd.iX+1;
1.682 + ClipFillLine(tl,tr,aClipRect);
1.683 + }
1.684 + PieTriangles(aStartQuad==1 || aStartQuad==2,aStart,aRect.Center(), aClipRect);
1.685 + PieTriangles(aEndQuad==0 || aEndQuad==3,aEnd,aRect.Center(), aClipRect);
1.686 + }
1.687 +
1.688 +/**
1.689 +Draws a filled triangle which forms part of a partially filled quadrant.
1.690 +
1.691 +@param aInside A boolean value indicating which side of the line to fill.
1.692 +@param aStart The start of the line which forms the hypotenuse of the triangle.
1.693 +@param aEnd The end of the line which forms the hypotenuse of the triangle.
1.694 +@param aClipRect The rectangle to which the pie is clipped.
1.695 +@see CSwDirectGdiEngine::PieShell
1.696 +*/
1.697 +void CSwDirectGdiEngine::PieTriangles(TBool aInside,const TPoint& aStart,const TPoint& aEnd, TRect aClipRect)
1.698 + {
1.699 + TInt x=aInside?aEnd.iX:aStart.iX;
1.700 + if (aStart.iX>aEnd.iX)
1.701 + {
1.702 + if (aInside)
1.703 + {
1.704 + x++;
1.705 + }
1.706 + else
1.707 + {
1.708 + x--;
1.709 + }
1.710 + }
1.711 + else
1.712 + {
1.713 + if (!aInside)
1.714 + {
1.715 + x++;
1.716 + }
1.717 + }
1.718 + TLinearDDA line;
1.719 + TPoint pt,left,right;
1.720 + line.Construct(aStart,aEnd);
1.721 + line.NextStep(pt);
1.722 + while(!line.NextStep(pt))
1.723 + {
1.724 + if (pt.iY==aEnd.iY) break;
1.725 + left.iX=Min(pt.iX,x);
1.726 + right.iX=Max(pt.iX,x);
1.727 + left.iY=right.iY=pt.iY;
1.728 + ClipFillLine(left,right,aClipRect);
1.729 + }
1.730 + }
1.731 +
1.732 +/**
1.733 +Draws a pie entirely contained in one quadrant.
1.734 +
1.735 +@param aRect The rectangle in which to draw the ellipse.
1.736 +@param aStart The arc start point.
1.737 +@param aEnd The arc end point.
1.738 +@param aQuad The quadrant containing the pie.
1.739 +@param aClipRect The rectangle to which the pie is clipped.
1.740 +*/
1.741 +void CSwDirectGdiEngine::PieSliver(const TRect& aRect,const TPoint& aStart,
1.742 + const TPoint& aEnd, TInt aQuad, TRect aClipRect)
1.743 + {
1.744 + TPoint center=aRect.Center(),left,right;
1.745 + TPoint nearinter(aStart),farinter(aEnd);
1.746 + if (Abs(nearinter.iY-center.iY)>Abs(farinter.iY-center.iY))
1.747 + {
1.748 + nearinter=aEnd;
1.749 + farinter=aStart;
1.750 + }
1.751 + TBool ellipseComplete = EFalse;
1.752 + TPoint pt[4];
1.753 + TSwDirectGdiEllipse ellipse;
1.754 + ellipse.Construct(aRect);
1.755 + TLinearDDA mainline;
1.756 + mainline.Construct(farinter,center);
1.757 + ellipseComplete = ellipse.SingleStep(pt[0],pt[1],pt[2],pt[3]);
1.758 + mainline.SingleStep(right);
1.759 + do {
1.760 + while(!ellipseComplete && pt[aQuad].iY!=right.iY)
1.761 + ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
1.762 + left=pt[aQuad];
1.763 + while(!ellipseComplete && pt[aQuad].iY==right.iY)
1.764 + {
1.765 + left=pt[aQuad];
1.766 + ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
1.767 + }
1.768 + if (right.iY==nearinter.iY || (ellipseComplete && (pt[0].iY != pt[2].iY)))
1.769 + break;
1.770 + if (left.iX>right.iX)
1.771 + {
1.772 + TInt temp=left.iX;
1.773 + left.iX=right.iX;
1.774 + right.iX=temp;
1.775 + }
1.776 + if(right==farinter && left.iX<=right.iX)
1.777 + {
1.778 + continue;
1.779 + }
1.780 + left.iX++;
1.781 + right.iX--;
1.782 + if (left.iX<=right.iX)
1.783 + ClipFillLine(left,right,aClipRect);
1.784 + }
1.785 + while(!mainline.NextStep(right));
1.786 + TPoint temppt;
1.787 + TLinearDDA line;
1.788 + line.Construct(nearinter,center);
1.789 + TBool linestat=EFalse;
1.790 + do
1.791 + linestat=line.SingleStep(temppt);
1.792 + while(temppt.iY!=right.iY && !linestat);
1.793 + do {
1.794 + do {
1.795 + left=temppt;
1.796 + linestat=line.SingleStep(temppt);
1.797 + }
1.798 + while(temppt.iY==right.iY && !linestat);
1.799 + if (ellipseComplete)
1.800 + break;
1.801 + if (left.iX>right.iX)
1.802 + {
1.803 + TInt temp=left.iX;
1.804 + left.iX=right.iX;
1.805 + right.iX=temp;
1.806 + }
1.807 + if(right==farinter && left.iX<=right.iX)
1.808 + {
1.809 + continue;
1.810 + }
1.811 + left.iX++;
1.812 + right.iX--;
1.813 + if (left.iX<=right.iX)
1.814 + ClipFillLine(left,right,aClipRect);
1.815 + }
1.816 + while(!mainline.NextStep(right));
1.817 + }
1.818 +