First public contribution.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
20 #include <graphics/fbsrasterizer.h>
24 class TArc : public TEllipse
27 void Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd);
28 TBool SingleStep(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
29 void Step(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr);
38 TBool iStartquadenabled;
39 TBool iEndquadenabled;
47 void TArc::Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd)
49 iStart=Intersection(aRect,aStart);
50 iEnd=Intersection(aRect,aEnd);
51 TEllipse::Construct(aRect);
56 iStartquadenabled=EFalse;
57 iEndquadenabled=EFalse;
61 TPoint center=aRect.Center();
62 if (iStart.iX>=center.iX) iStartquad=1;
63 if (iStart.iY>=center.iY) iStartquad+=2;
64 if (iEnd.iX>=center.iX) iEndquad=1;
65 if (iEnd.iY>=center.iY) iEndquad+=2;
66 if (iStartquad!=iEndquad)
68 if (iStartquad==0 && iEndquad==1)
73 else if (iStartquad==0 && iEndquad==3)
75 else if (iStartquad==1 && iEndquad==2)
77 else if (iStartquad==1 && iEndquad==3)
82 else if (iStartquad==2 && iEndquad==0)
87 else if (iStartquad==2 && iEndquad==1)
89 else if (iStartquad==3 && iEndquad==0)
91 else if (iStartquad==3 && iEndquad==2)
97 else if (iStart==iEnd)
107 if (iStartquad==0 && (iStart.iX<iEnd.iX || iStart.iY>iEnd.iY))
114 else if (iStartquad==1 && (iStart.iX<iEnd.iX || iStart.iY<iEnd.iY))
121 else if (iStartquad==2 && (iStart.iX>iEnd.iX || iStart.iY>iEnd.iY))
128 else if (iStartquad==3 && (iStart.iX>iEnd.iX || iStart.iY<iEnd.iY))
136 if (iStartquad==1 || iStartquad==2)
137 iStartquadenabled=ETrue;
138 if (iEndquad==0 || iEndquad==3)
139 iEndquadenabled=ETrue;
140 iStartquaddone=EFalse;
144 TBool TArc::SingleStep(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,
145 TBool& aDoTr,TPoint& aBottomLeft,TBool& aDoBl,
146 TPoint& aBottomRight,TBool& aDoBr)
148 TBool finished=TEllipse::SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight);
149 Step(aTopLeft,aDoTl,aTopRight,aDoTr,aBottomLeft,aDoBl,aBottomRight,aDoBr);
154 void TArc::Step(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,TBool& aDoTr,
155 TPoint& aBottomLeft,TBool& aDoBl,TPoint& aBottomRight,TBool& aDoBr)
163 if (!iStartquadenabled)
165 if (iStartquad==0 && aTopLeft.iX<=iStart.iX && aTopLeft.iY>=iStart.iY)
167 iStartquadenabled=ETrue;
168 iStartquaddone=ETrue;
170 if (iStartquad==3 && aBottomRight.iX>=iStart.iX && aBottomRight.iY<=iStart.iY)
172 iStartquadenabled=ETrue;
173 iStartquaddone=ETrue;
178 if (iStartquad==1 && (aTopRight.iX>iStart.iX || aTopRight.iY>iStart.iY))
180 iStartquadenabled=EFalse;
181 iStartquaddone=ETrue;
183 if (iStartquad==2 && (aBottomLeft.iX<iStart.iX || aBottomLeft.iY<iStart.iY))
185 iStartquadenabled=EFalse;
186 iStartquaddone=ETrue;
194 if (iEndquad==0 && (aTopLeft.iX<iEnd.iX || aTopLeft.iY>iEnd.iY))
196 iEndquadenabled=EFalse;
199 if (iEndquad==3 && (aBottomRight.iX>iEnd.iX || aBottomRight.iY<iEnd.iY))
201 iEndquadenabled=EFalse;
207 if (iEndquad==1 && aTopRight.iX>=iEnd.iX && aTopRight.iY>=iEnd.iY)
209 iEndquadenabled=ETrue;
212 if (iEndquad==2 && aBottomLeft.iX<=iEnd.iX && aBottomLeft.iY<=iEnd.iY)
214 iEndquadenabled=ETrue;
219 if (iStartquad!=iEndquad)
221 if (iStartquadenabled)
223 if (iStartquad==0) aDoTl=ETrue;
224 else if (iStartquad==1) aDoTr=ETrue;
225 else if (iStartquad==2) aDoBl=ETrue;
226 else if (iStartquad==3) aDoBr=ETrue;
230 if (iEndquad==0) aDoTl=ETrue;
231 else if (iEndquad==1) aDoTr=ETrue;
232 else if (iEndquad==2) aDoBl=ETrue;
233 else if (iEndquad==3) aDoBr=ETrue;
240 if (iStartquadenabled && iEndquadenabled)
242 if (iStartquad==0) aDoTl=ETrue;
243 else if (iStartquad==1) aDoTr=ETrue;
244 else if (iStartquad==2) aDoBl=ETrue;
245 else if (iStartquad==3) aDoBr=ETrue;
250 if (iStartquadenabled || iEndquadenabled)
252 if (iStartquad==0) aDoTl=ETrue;
253 else if (iStartquad==1) aDoTr=ETrue;
254 else if (iStartquad==2) aDoBl=ETrue;
255 else if (iStartquad==3) aDoBr=ETrue;
259 if (aTopLeft.iX==aTopRight.iX)
261 if (aDoTl && aDoTr) aDoTr=EFalse;
262 if (aDoBl && aDoBr) aDoBr=EFalse;
267 // Pie and Arc drawing functions
273 The function provides a concrete implementation of the pure virtual
274 function <code>CGraphicsContext::DrawArc()</code>. The function
275 behaviour is the same as documented in that class.
277 EXPORT_C void CFbsBitGc::DrawArc(const TRect& aRect,const TPoint& aStartradius,
278 const TPoint& aEndradius)
280 if (!iPenStyle || !iPenSize.iWidth || !iPenSize.iHeight || aRect.IsEmpty() || CheckDevice(aRect))
285 iDevice->TruncateRect(rcpy);
286 TRect arcBoundingRect(rcpy);
287 arcBoundingRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
288 if (!arcBoundingRect.Intersects(iUserClipRect))
292 iDevice->DrawingBegin();
293 PieArcOutline(rcpy,aStartradius+iOrigin,aEndradius+iOrigin,EFalse);
294 iDevice->DrawingEnd();
298 Draws and fills a pie slice.
300 The function provides a concrete implementation of the pure virtual
301 function <code>CGraphicsContext::DrawPie()</code>. The function
302 behaviour is the same as documented in that class.
304 EXPORT_C void CFbsBitGc::DrawPie(const TRect& aRect,const TPoint& aStartradius,
305 const TPoint& aEndradius)
307 if (CheckDevice(aRect))
312 iDevice->TruncateRect(rcpy);
313 TRect pieBoundingRect(rcpy);
314 pieBoundingRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1);
315 if (!pieBoundingRect.Intersects(iUserClipRect))
318 TPoint startIntersect = aStartradius + iOrigin, endIntersect = aEndradius + iOrigin;
319 TInt startQuadrant, endQuadrant;
321 const TBool isEllipse = AnalyseEllipse(
322 rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);
325 iDevice->DrawingBegin(&iBrushBitmap);
326 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
327 if (iBrushStyle!=ENullBrush)
332 PieFill(rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants);
334 if (iPenStyle!=ENullPen && iPenSize.iWidth>0 && iPenSize.iHeight>0)
335 PieArcOutline(rcpy,aStartradius+iOrigin,aEndradius+iOrigin,ETrue);
338 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
340 iDevice->DrawingEnd(&iBrushBitmap);
344 Determine the pie constructed within the given rectangle.
346 @param rc Input - The bounding rectangle.
347 @param srad Input/Output - The intersection point from the geometric centre
348 of the ellipse to the given start point
349 @param erad Input/Output - The intersection point from the geometric centre
350 of the ellipse to the given end point
351 @param startq Output - The start quadrant
352 @param endq Output - The end quadrant
353 @param quads Output - Quadrants
354 @pre Input params rc, srad, erad are to be given.
355 @post Output params srad, erad, startq, endq, quads will be populated.
356 @return ETrue if the pie is an ellipse, otherwise EFalse.
358 TBool CFbsBitGc::AnalyseEllipse(const TRect& rc,TPoint& srad,TPoint& erad,
359 TInt& startq,TInt& endq,TBool* quads)
363 const TPoint center = rc.Center();
365 srad=ellipse.Intersection(rc,srad);
366 erad=ellipse.Intersection(rc,erad);
376 const TInt startx = srad.iX - center.iX, starty = srad.iY - center.iY;
377 const TInt endx = erad.iX - center.iX, endy = erad.iY - center.iY;
378 if (startx>=0) startq=1;
379 if (starty>=0) startq+=2;
381 if (endy>=0) endq+=2;
382 quads[1]=EFalse,quads[2]=EFalse,quads[3]=EFalse,quads[4]=EFalse; // complete quadrants to draw
383 quads[0]=EFalse; // ellipse is a sliver completely within a quadrant
386 if (startq==0 && (startx<endx || starty>endy))
392 else if (startq==1 && (startx<endx || starty<endy))
398 else if (startq==2 && (startx>endx || starty>endy))
404 else if (startq==3 && (startx>endx || starty<endy))
410 else quads[0]=ETrue; // "slice"
414 if (startq==0 && endq==1)
419 else if (startq==0 && endq==3)
421 else if (startq==1 && endq==2)
423 else if (startq==1 && endq==3)
428 else if (startq==2 && endq==0)
433 else if (startq==2 && endq==1)
435 else if (startq==3 && endq==0)
437 else if (startq==3 && endq==2)
446 void CFbsBitGc::PieArcOutline(const TRect& ellrect,const TPoint& startradius,
447 const TPoint& endradius,TBool pie)
449 // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
450 TInt dotparam=iDotParam;
453 TInt halfpenwidth=iPenSize.iWidth>>1;
454 TInt halfpenheight=iPenSize.iHeight>>1;
455 TInt otherhalfwidth=(iPenSize.iWidth+1)>>1;
456 TInt otherhalfheight=(iPenSize.iHeight+1)>>1;
457 rcpy.iTl.iX-=halfpenwidth;
458 rcpy.iTl.iY-=halfpenheight;
459 rcpy.iBr.iX+=otherhalfwidth;
460 rcpy.iBr.iY+=otherhalfheight;
462 for(TInt count=0;count<iDefaultRegionPtr->Count();count++)
464 iClipRect=(*iDefaultRegionPtr)[count];
465 if (!iClipRect.Intersects(rcpy))
467 iClipRect.Intersection(rcpy);
468 if (UserClipRect(iClipRect)) continue;
470 arc.Construct(ellrect,startradius,endradius);
471 iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1);
472 TBool dotl,dotr,dobl,dobr;
473 while(!arc.SingleStep(pt[0],dotl,pt[1],dotr,pt[2],dobl,pt[3],dobr))
475 if (dotl) PenDrawClipped(pt[0]);
476 if (dotr) PenDrawClipped(pt[1]);
477 if (dobl) PenDrawClipped(pt[2]);
478 if (dobr) PenDrawClipped(pt[3]);
479 iDotParam+=iDotDirection;
481 if (pt[0].iY==pt[2].iY)
483 if (dotl) PenDrawClipped(pt[0]);
484 if (dotr) PenDrawClipped(pt[1]);
489 const TPoint center = ellrect.Center();
491 line.Construct(arc.iStart,center);
492 line.SingleStep(temp);
493 while(!line.SingleStep(temp))
495 PenDrawClipped(temp);
496 iDotParam+=iDotDirection;
498 line.Construct(arc.iEnd,center);
499 line.SingleStep(temp);
500 while(!line.SingleStep(temp))
502 PenDrawClipped(temp);
503 iDotParam+=iDotDirection;
505 PenDrawClipped(center);
507 iDevice->iDrawDevice->UpdateRegion(iClipRect);
512 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
513 void CFbsBitGc::PieFill(const TRect& ellrect, const TPoint& aStartIntersect, const TPoint& aEndIntersect,
514 TInt aStartQuadrant, TInt aEndQuadrant, const TBool* aQuadrants)
516 // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect
518 const TInt limit = iDefaultRegionPtr->Count();
519 for(TInt count=0;count<limit;count++)
521 iClipRect=(*iDefaultRegionPtr)[count];
522 if (!iClipRect.Intersects(ellrect))
524 iClipRect.Intersection(ellrect);
525 if (UserClipRect(iClipRect)) continue;
527 PieShell(ellrect, aStartIntersect, aEndIntersect, aQuadrants, aStartQuadrant, aEndQuadrant);
529 PieSliver(ellrect, aStartIntersect, aEndIntersect, aStartQuadrant);
530 iDevice->iDrawDevice->UpdateRegion(iClipRect);
534 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
535 void CFbsBitGc::PieShell(const TRect& ellrect,const TPoint& startradius,
536 const TPoint& endradius, const TBool* quads, TInt startquad, TInt endquad)
539 ellipse.Construct(ellrect);
540 TInt c=ellrect.Center().iX;
543 TBool donestart=EFalse,doneend=EFalse;
544 TBool todostart=EFalse,todoend=EFalse;
545 while(!ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]))
547 if (pt[startquad].iY==startradius.iY)
549 if (pt[endquad].iY==endradius.iY)
559 if (quads[1] || (endquad==0 && !doneend)) // tl quadrant, half top end chord
562 if (quads[2] || (startquad==1 && !donestart)) // tr quadrant, half top start chord
565 if (quads[3] || (startquad==2 && !donestart)) // bl quadrant, half top start chord
568 if (quads[4] || (endquad==3 && !doneend)) // br quadrant, half top end chord
573 // do partial quadrants
579 tr.iX=startradius.iX;
582 else if (startquad==3)
584 bl.iX=startradius.iX;
609 if (pt[0].iY==pt[2].iY) // congruent mid lines
611 if (pt[startquad].iY==startradius.iY)
613 if (pt[endquad].iY==endradius.iY)
619 TBool leftflag=EFalse,rightflag=EFalse;
620 if (quads[1] || (endquad==0 && !doneend) ||
621 quads[3] || (startquad==2 && !donestart) ||
622 (todostart && startquad==0) || (todoend && endquad==2))
624 if (quads[2] || (startquad==1 && !donestart) ||
625 quads[4] || (endquad==3 && !doneend) ||
626 (todostart && startquad==3) || (todoend && endquad==1))
628 if (leftflag) tl.iX=pt[0].iX;
629 if (rightflag) tr.iX=pt[1].iX;
634 tl.iY=ellrect.Center().iY;
636 if (startquad==3) tr.iX=startradius.iX-1;
637 if (endquad==2) tl.iX=endradius.iX+1;
640 PieTriangles(startquad==1 || startquad==2,startradius,ellrect.Center());
641 PieTriangles(endquad==0 || endquad==3,endradius,ellrect.Center());
644 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
645 void CFbsBitGc::PieTriangles(TBool aInside,const TPoint& aStart,const TPoint& aEnd)
647 TInt x=aInside?aEnd.iX:aStart.iX;
648 if (aStart.iX>aEnd.iX)
659 TPoint pt,left,right;
660 line.Construct(aStart,aEnd);
662 while(!line.NextStep(pt))
664 if (pt.iY==aEnd.iY) break;
665 left.iX=Min(pt.iX,x);
666 right.iX=Max(pt.iX,x);
667 left.iY=right.iY=pt.iY;
668 ClipFillLine(left,right);
672 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
673 void CFbsBitGc::PieSliver(const TRect& ellrect,const TPoint& startradius,
674 const TPoint& endradius,TInt quad)
676 TPoint center=ellrect.Center(),left,right;
677 TPoint nearinter(startradius),farinter(endradius);
678 if (Abs(nearinter.iY-center.iY)>Abs(farinter.iY-center.iY))
681 farinter=startradius;
683 TBool ellipseComplete = EFalse;
686 ellipse.Construct(ellrect);
688 mainline.Construct(farinter,center);
689 ellipseComplete = ellipse.SingleStep(pt[0],pt[1],pt[2],pt[3]);
690 mainline.SingleStep(right);
692 while(!ellipseComplete && pt[quad].iY!=right.iY)
693 ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
695 while(!ellipseComplete && pt[quad].iY==right.iY)
698 ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]);
700 if (right.iY==nearinter.iY || (ellipseComplete && (pt[0].iY != pt[2].iY)))
702 if (left.iX>right.iX)
708 if(right==farinter && left.iX<=right.iX)
714 if (left.iX<=right.iX)
715 ClipFillLine(left,right);
717 while(!mainline.NextStep(right));
720 line.Construct(nearinter,center);
721 TBool linestat=EFalse;
723 linestat=line.SingleStep(temppt);
724 while(temppt.iY!=right.iY && !linestat);
728 linestat=line.SingleStep(temppt);
730 while(temppt.iY==right.iY && !linestat);
733 if (left.iX>right.iX)
739 if(right==farinter && left.iX<=right.iX)
745 if (left.iX<=right.iX)
746 ClipFillLine(left,right);
748 while(!mainline.NextStep(right));