|
1 // Copyright (c) 2007-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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "swdirectgdiengine.h" |
|
17 #include "swdirectgdiellipse.h" |
|
18 |
|
19 |
|
20 /** |
|
21 A utility class to efficiently draw arcs. |
|
22 @see CSwDirectGdiEngine::PieArcOutline |
|
23 |
|
24 @internalComponent |
|
25 */ |
|
26 class TSwDirectGdiArc : public TSwDirectGdiEllipse |
|
27 { |
|
28 public: |
|
29 void Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd); |
|
30 TBool SingleStep(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr); |
|
31 void Step(TPoint& aTl,TBool& aDoTl,TPoint& aTr,TBool& aDoTr,TPoint& aBl,TBool& aDoBl,TPoint& aBr,TBool& aDoBr); |
|
32 public: |
|
33 TPoint iStart; |
|
34 TPoint iEnd; |
|
35 private: |
|
36 TBool iTlquad; |
|
37 TBool iTrquad; |
|
38 TBool iBlquad; |
|
39 TBool iBrquad; |
|
40 TBool iStartquadenabled; |
|
41 TBool iEndquadenabled; |
|
42 TBool iStartquaddone; |
|
43 TBool iEndquaddone; |
|
44 TInt iStartquad; |
|
45 TInt iEndquad; |
|
46 TBool iSlice; |
|
47 }; |
|
48 |
|
49 /** |
|
50 Constructs a TSwDirectGdiArc. |
|
51 @param aRect The bounding rectangle. |
|
52 @param aStart The arc start point. |
|
53 @param aEnd The arc end point. |
|
54 @see CSwDirectGdiEngine::PieArcOutline |
|
55 */ |
|
56 void TSwDirectGdiArc::Construct(const TRect& aRect,const TPoint& aStart,const TPoint& aEnd) |
|
57 { |
|
58 iStart=Intersection(aRect,aStart); |
|
59 iEnd=Intersection(aRect,aEnd); |
|
60 TSwDirectGdiEllipse::Construct(aRect); |
|
61 iTlquad=EFalse; |
|
62 iTrquad=EFalse; |
|
63 iBlquad=EFalse; |
|
64 iBrquad=EFalse; |
|
65 iStartquadenabled=EFalse; |
|
66 iEndquadenabled=EFalse; |
|
67 iSlice=EFalse; |
|
68 iStartquad=0; |
|
69 iEndquad=0; |
|
70 TPoint center=aRect.Center(); |
|
71 if (iStart.iX>=center.iX) iStartquad=1; |
|
72 if (iStart.iY>=center.iY) iStartquad+=2; |
|
73 if (iEnd.iX>=center.iX) iEndquad=1; |
|
74 if (iEnd.iY>=center.iY) iEndquad+=2; |
|
75 if (iStartquad!=iEndquad) |
|
76 { |
|
77 if (iStartquad==0 && iEndquad==1) |
|
78 { |
|
79 iBlquad=ETrue; |
|
80 iBrquad=ETrue; |
|
81 } |
|
82 else if (iStartquad==0 && iEndquad==3) |
|
83 iBlquad=ETrue; |
|
84 else if (iStartquad==1 && iEndquad==2) |
|
85 iTlquad=ETrue; |
|
86 else if (iStartquad==1 && iEndquad==3) |
|
87 { |
|
88 iTlquad=ETrue; |
|
89 iBlquad=ETrue; |
|
90 } |
|
91 else if (iStartquad==2 && iEndquad==0) |
|
92 { |
|
93 iTrquad=ETrue; |
|
94 iBrquad=ETrue; |
|
95 } |
|
96 else if (iStartquad==2 && iEndquad==1) |
|
97 iBrquad=ETrue; |
|
98 else if (iStartquad==3 && iEndquad==0) |
|
99 iTrquad=ETrue; |
|
100 else if (iStartquad==3 && iEndquad==2) |
|
101 { |
|
102 iTlquad=ETrue; |
|
103 iTrquad=ETrue; |
|
104 } |
|
105 } |
|
106 else if (iStart==iEnd) |
|
107 { |
|
108 iTlquad=ETrue; |
|
109 iTrquad=ETrue; |
|
110 iBlquad=ETrue; |
|
111 iBrquad=ETrue; |
|
112 } |
|
113 else |
|
114 { |
|
115 iSlice=ETrue; |
|
116 if (iStartquad==0 && (iStart.iX<iEnd.iX || iStart.iY>iEnd.iY)) |
|
117 { |
|
118 iTrquad=ETrue; |
|
119 iBlquad=ETrue; |
|
120 iBrquad=ETrue; |
|
121 iSlice=EFalse; |
|
122 } |
|
123 else if (iStartquad==1 && (iStart.iX<iEnd.iX || iStart.iY<iEnd.iY)) |
|
124 { |
|
125 iTlquad=ETrue; |
|
126 iBlquad=ETrue; |
|
127 iBrquad=ETrue; |
|
128 iSlice=EFalse; |
|
129 } |
|
130 else if (iStartquad==2 && (iStart.iX>iEnd.iX || iStart.iY>iEnd.iY)) |
|
131 { |
|
132 iTlquad=ETrue; |
|
133 iTrquad=ETrue; |
|
134 iBrquad=ETrue; |
|
135 iSlice=EFalse; |
|
136 } |
|
137 else if (iStartquad==3 && (iStart.iX>iEnd.iX || iStart.iY<iEnd.iY)) |
|
138 { |
|
139 iTlquad=ETrue; |
|
140 iTrquad=ETrue; |
|
141 iBlquad=ETrue; |
|
142 iSlice=EFalse; |
|
143 } |
|
144 } |
|
145 if (iStartquad==1 || iStartquad==2) |
|
146 iStartquadenabled=ETrue; |
|
147 if (iEndquad==0 || iEndquad==3) |
|
148 iEndquadenabled=ETrue; |
|
149 iStartquaddone=EFalse; |
|
150 iEndquaddone=EFalse; |
|
151 } |
|
152 |
|
153 /** |
|
154 Produces the next stage creating an arc, taking four points (the corners of |
|
155 the rectangle the arc should fill) as parameters. |
|
156 |
|
157 @param aTopLeft Top left corner of rectangle. |
|
158 @param aDoTl Span the top left quadrant. |
|
159 @param aTopRight Top right corner of rectangle. |
|
160 @param aDoTr Span the top right quadrant. |
|
161 @param aBottomLeft Bottom left corner of rectangle. |
|
162 @param aDoBl Span the bottom left quadrant. |
|
163 @param aBottomRight Bottom right corner of rectangle. |
|
164 @param aDoBr Span the bottom right quadrant. |
|
165 @return TBool ETrue if step completed successfully. |
|
166 @see TSwDirectGdiEllipse::SingleStep |
|
167 */ |
|
168 TBool TSwDirectGdiArc::SingleStep(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight, |
|
169 TBool& aDoTr,TPoint& aBottomLeft,TBool& aDoBl, |
|
170 TPoint& aBottomRight,TBool& aDoBr) |
|
171 { |
|
172 TBool finished=TSwDirectGdiEllipse::SingleStep(aTopLeft,aTopRight,aBottomLeft,aBottomRight); |
|
173 Step(aTopLeft,aDoTl,aTopRight,aDoTr,aBottomLeft,aDoBl,aBottomRight,aDoBr); |
|
174 |
|
175 return finished; |
|
176 } |
|
177 |
|
178 /** |
|
179 Determines how many quadrants are left to draw. |
|
180 |
|
181 @param aTopLeft Top left corner of rectangle. |
|
182 @param aDoTl Span the top left quadrant. |
|
183 @param aTopRight Top right corner of rectangle. |
|
184 @param aDoTr Span the top right quadrant. |
|
185 @param aBottomLeft Bottom left corner of rectangle. |
|
186 @param aDoBl Span the bottom left quadrant. |
|
187 @param aBottomRight Bottom right corner of rectangle. |
|
188 @param aDoBr Span the bottom right quadrant. |
|
189 @see TSwDirectGdiArc::SingleStep |
|
190 @see TSwDirectGdiArc::Construct |
|
191 */ |
|
192 void TSwDirectGdiArc::Step(TPoint& aTopLeft,TBool& aDoTl,TPoint& aTopRight,TBool& aDoTr, |
|
193 TPoint& aBottomLeft,TBool& aDoBl,TPoint& aBottomRight,TBool& aDoBr) |
|
194 { |
|
195 aDoTl=iTlquad; |
|
196 aDoTr=iTrquad; |
|
197 aDoBl=iBlquad; |
|
198 aDoBr=iBrquad; |
|
199 if (!iStartquaddone) |
|
200 { |
|
201 if (!iStartquadenabled) |
|
202 { |
|
203 if (iStartquad==0 && aTopLeft.iX<=iStart.iX && aTopLeft.iY>=iStart.iY) |
|
204 { |
|
205 iStartquadenabled=ETrue; |
|
206 iStartquaddone=ETrue; |
|
207 } |
|
208 if (iStartquad==3 && aBottomRight.iX>=iStart.iX && aBottomRight.iY<=iStart.iY) |
|
209 { |
|
210 iStartquadenabled=ETrue; |
|
211 iStartquaddone=ETrue; |
|
212 } |
|
213 } |
|
214 else |
|
215 { |
|
216 if (iStartquad==1 && (aTopRight.iX>iStart.iX || aTopRight.iY>iStart.iY)) |
|
217 { |
|
218 iStartquadenabled=EFalse; |
|
219 iStartquaddone=ETrue; |
|
220 } |
|
221 if (iStartquad==2 && (aBottomLeft.iX<iStart.iX || aBottomLeft.iY<iStart.iY)) |
|
222 { |
|
223 iStartquadenabled=EFalse; |
|
224 iStartquaddone=ETrue; |
|
225 } |
|
226 } |
|
227 } |
|
228 if (!iEndquaddone) |
|
229 { |
|
230 if (iEndquadenabled) |
|
231 { |
|
232 if (iEndquad==0 && (aTopLeft.iX<iEnd.iX || aTopLeft.iY>iEnd.iY)) |
|
233 { |
|
234 iEndquadenabled=EFalse; |
|
235 iEndquaddone=ETrue; |
|
236 } |
|
237 if (iEndquad==3 && (aBottomRight.iX>iEnd.iX || aBottomRight.iY<iEnd.iY)) |
|
238 { |
|
239 iEndquadenabled=EFalse; |
|
240 iEndquaddone=ETrue; |
|
241 } |
|
242 } |
|
243 else |
|
244 { |
|
245 if (iEndquad==1 && aTopRight.iX>=iEnd.iX && aTopRight.iY>=iEnd.iY) |
|
246 { |
|
247 iEndquadenabled=ETrue; |
|
248 iEndquaddone=ETrue; |
|
249 } |
|
250 if (iEndquad==2 && aBottomLeft.iX<=iEnd.iX && aBottomLeft.iY<=iEnd.iY) |
|
251 { |
|
252 iEndquadenabled=ETrue; |
|
253 iEndquaddone=ETrue; |
|
254 } |
|
255 } |
|
256 } |
|
257 if (iStartquad!=iEndquad) |
|
258 { |
|
259 if (iStartquadenabled) |
|
260 { |
|
261 if (iStartquad==0) aDoTl=ETrue; |
|
262 else if (iStartquad==1) aDoTr=ETrue; |
|
263 else if (iStartquad==2) aDoBl=ETrue; |
|
264 else if (iStartquad==3) aDoBr=ETrue; |
|
265 } |
|
266 if (iEndquadenabled) |
|
267 { |
|
268 if (iEndquad==0) aDoTl=ETrue; |
|
269 else if (iEndquad==1) aDoTr=ETrue; |
|
270 else if (iEndquad==2) aDoBl=ETrue; |
|
271 else if (iEndquad==3) aDoBr=ETrue; |
|
272 } |
|
273 } |
|
274 else |
|
275 { |
|
276 if (iSlice) |
|
277 { |
|
278 if (iStartquadenabled && iEndquadenabled) |
|
279 { |
|
280 if (iStartquad==0) aDoTl=ETrue; |
|
281 else if (iStartquad==1) aDoTr=ETrue; |
|
282 else if (iStartquad==2) aDoBl=ETrue; |
|
283 else if (iStartquad==3) aDoBr=ETrue; |
|
284 } |
|
285 } |
|
286 else |
|
287 { |
|
288 if (iStartquadenabled || iEndquadenabled) |
|
289 { |
|
290 if (iStartquad==0) aDoTl=ETrue; |
|
291 else if (iStartquad==1) aDoTr=ETrue; |
|
292 else if (iStartquad==2) aDoBl=ETrue; |
|
293 else if (iStartquad==3) aDoBr=ETrue; |
|
294 } |
|
295 } |
|
296 } |
|
297 if (aTopLeft.iX==aTopRight.iX) |
|
298 { |
|
299 if (aDoTl && aDoTr) aDoTr=EFalse; |
|
300 if (aDoBl && aDoBr) aDoBr=EFalse; |
|
301 } |
|
302 } |
|
303 |
|
304 // |
|
305 // Pie and Arc drawing functions |
|
306 // |
|
307 |
|
308 /** |
|
309 @see MDirectGdiEngine::DrawArc() |
|
310 */ |
|
311 void CSwDirectGdiEngine::DrawArc(const TRect& aRect,const TPoint& aStart, |
|
312 const TPoint& aEnd) |
|
313 { |
|
314 TRect rcpy(aRect); |
|
315 rcpy.Move(iOrigin); |
|
316 TruncateRect(rcpy); |
|
317 TRect targetRect(rcpy); |
|
318 targetRect.Grow((iPenSize.iWidth>>1)+1,(iPenSize.iHeight>>1)+1); |
|
319 PieArcOutline(rcpy,aStart+iOrigin,aEnd+iOrigin,EFalse); |
|
320 } |
|
321 |
|
322 /** |
|
323 @see MDirectGdiEngine::DrawPie() |
|
324 */ |
|
325 void CSwDirectGdiEngine::DrawPie(const TRect& aRect,const TPoint& aStart, |
|
326 const TPoint& aEnd) |
|
327 { |
|
328 TRect rcpy(aRect); |
|
329 rcpy.Move(iOrigin); |
|
330 TruncateRect(rcpy); |
|
331 TPoint startIntersect = aStart + iOrigin, endIntersect = aEnd + iOrigin; |
|
332 TInt startQuadrant, endQuadrant; |
|
333 TBool quadrants[5]; |
|
334 const TBool isEllipse = AnalyseEllipse( |
|
335 rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants); |
|
336 |
|
337 if (iBrushStyle!=DirectGdi::ENullBrush) |
|
338 { |
|
339 if (isEllipse) |
|
340 EllipseFill(rcpy); |
|
341 else |
|
342 PieFill(rcpy, startIntersect, endIntersect, startQuadrant, endQuadrant, quadrants); |
|
343 } |
|
344 if ((iPenStyle!=DirectGdi::ENullPen) && (iPenSize.iWidth>0) && (iPenSize.iHeight>0)) |
|
345 PieArcOutline(rcpy,aStart+iOrigin,aEnd+iOrigin,ETrue); |
|
346 } |
|
347 |
|
348 /** |
|
349 Calculates which quadrants are completely filled and which quadrants contain the |
|
350 start and end points. |
|
351 |
|
352 @param aRect The bounding rectangle. |
|
353 @param aStart The arc start point. |
|
354 @param aEnd The arc end point. |
|
355 @param aStartQuad On return, contains the quadrant which contains aStart. |
|
356 @param aEndQuad On return, contains the quadrant which contains aEnd. |
|
357 @param aQuads On return, populates an array of full quadrants to fill. |
|
358 @pre Input params aRect, aStart, aEnd are to be given. |
|
359 @post Output params aStart, aEnd, aStartQuad, aEndQuad, aQuads will be populated. |
|
360 @return ETrue if the pie is an ellipse, otherwise EFalse. |
|
361 */ |
|
362 TBool CSwDirectGdiEngine::AnalyseEllipse(const TRect& aRect,TPoint& aStart,TPoint& aEnd, |
|
363 TInt& aStartQuad,TInt& aEndQuad,TBool* aQuads) |
|
364 { |
|
365 aStartQuad=0; |
|
366 aEndQuad=0; |
|
367 const TPoint center = aRect.Center(); |
|
368 TSwDirectGdiEllipse ellipse; |
|
369 aStart=ellipse.Intersection(aRect,aStart); |
|
370 aEnd=ellipse.Intersection(aRect,aEnd); |
|
371 if (aStart==aEnd) |
|
372 { |
|
373 aQuads[0]=EFalse; |
|
374 aQuads[1]=ETrue; |
|
375 aQuads[2]=ETrue; |
|
376 aQuads[3]=ETrue; |
|
377 aQuads[4]=ETrue; |
|
378 return ETrue; |
|
379 } |
|
380 const TInt startx = aStart.iX - center.iX, starty = aStart.iY - center.iY; |
|
381 const TInt endx = aEnd.iX - center.iX, endy = aEnd.iY - center.iY; |
|
382 if (startx>=0) aStartQuad=1; |
|
383 if (starty>=0) aStartQuad+=2; |
|
384 if (endx>=0) aEndQuad=1; |
|
385 if (endy>=0) aEndQuad+=2; |
|
386 aQuads[1]=EFalse,aQuads[2]=EFalse,aQuads[3]=EFalse,aQuads[4]=EFalse; // complete quadrants to draw |
|
387 aQuads[0]=EFalse; // ellipse is a sliver completely within a quadrant |
|
388 if (aStartQuad==aEndQuad) |
|
389 { |
|
390 if (aStartQuad==0 && (startx<endx || starty>endy)) |
|
391 { |
|
392 aQuads[2]=ETrue; |
|
393 aQuads[3]=ETrue; |
|
394 aQuads[4]=ETrue; |
|
395 } |
|
396 else if (aStartQuad==1 && (startx<endx || starty<endy)) |
|
397 { |
|
398 aQuads[1]=ETrue; |
|
399 aQuads[3]=ETrue; |
|
400 aQuads[4]=ETrue; |
|
401 } |
|
402 else if (aStartQuad==2 && (startx>endx || starty>endy)) |
|
403 { |
|
404 aQuads[1]=ETrue; |
|
405 aQuads[2]=ETrue; |
|
406 aQuads[4]=ETrue; |
|
407 } |
|
408 else if (aStartQuad==3 && (startx>endx || starty<endy)) |
|
409 { |
|
410 aQuads[1]=ETrue; |
|
411 aQuads[2]=ETrue; |
|
412 aQuads[3]=ETrue; |
|
413 } |
|
414 else aQuads[0]=ETrue; // "slice" |
|
415 } |
|
416 else |
|
417 { |
|
418 if (aStartQuad==0 && aEndQuad==1) |
|
419 { |
|
420 aQuads[3]=ETrue; |
|
421 aQuads[4]=ETrue; |
|
422 } |
|
423 else if (aStartQuad==0 && aEndQuad==3) |
|
424 aQuads[3]=ETrue; |
|
425 else if (aStartQuad==1 && aEndQuad==2) |
|
426 aQuads[1]=ETrue; |
|
427 else if (aStartQuad==1 && aEndQuad==3) |
|
428 { |
|
429 aQuads[1]=ETrue; |
|
430 aQuads[3]=ETrue; |
|
431 } |
|
432 else if (aStartQuad==2 && aEndQuad==0) |
|
433 { |
|
434 aQuads[2]=ETrue; |
|
435 aQuads[4]=ETrue; |
|
436 } |
|
437 else if (aStartQuad==2 && aEndQuad==1) |
|
438 aQuads[4]=ETrue; |
|
439 else if (aStartQuad==3 && aEndQuad==0) |
|
440 aQuads[2]=ETrue; |
|
441 else if (aStartQuad==3 && aEndQuad==2) |
|
442 { |
|
443 aQuads[1]=ETrue; |
|
444 aQuads[2]=ETrue; |
|
445 } |
|
446 } |
|
447 return EFalse; |
|
448 } |
|
449 |
|
450 /** |
|
451 Draws the outline of a pie or arc. |
|
452 |
|
453 @param aRect The bounding rectangle. |
|
454 @param aStart The arc start point. |
|
455 @param aEnd The arc end point. |
|
456 @param aPie If this is the outline for a pie ETrue, else EFalse |
|
457 */ |
|
458 void CSwDirectGdiEngine::PieArcOutline(const TRect& aRect,const TPoint& aStart, |
|
459 const TPoint& aEnd,TBool aPie) |
|
460 { |
|
461 // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect |
|
462 TInt dotparam=iDotParam; |
|
463 TRect rcpy(aRect); |
|
464 TPoint pt[4]; |
|
465 TInt halfpenwidth=iPenSize.iWidth>>1; |
|
466 TInt halfpenheight=iPenSize.iHeight>>1; |
|
467 TInt otherhalfwidth=(iPenSize.iWidth+1)>>1; |
|
468 TInt otherhalfheight=(iPenSize.iHeight+1)>>1; |
|
469 rcpy.iTl.iX-=halfpenwidth; |
|
470 rcpy.iTl.iY-=halfpenheight; |
|
471 rcpy.iBr.iX+=otherhalfwidth; |
|
472 rcpy.iBr.iY+=otherhalfheight; |
|
473 TRect clipRect(0,0,0,0); |
|
474 for(TInt count=0;count<iDefaultRegionPtr->Count();count++) |
|
475 { |
|
476 clipRect=(*iDefaultRegionPtr)[count]; |
|
477 if (!clipRect.Intersects(rcpy)) |
|
478 continue; |
|
479 clipRect.Intersection(rcpy); |
|
480 TSwDirectGdiArc arc; |
|
481 arc.Construct(aRect,aStart,aEnd); |
|
482 iDotParam=Max(iPenSize.iWidth>>1,iPenSize.iHeight>>1); |
|
483 TBool dotl,dotr,dobl,dobr; |
|
484 while(!arc.SingleStep(pt[0],dotl,pt[1],dotr,pt[2],dobl,pt[3],dobr)) |
|
485 { |
|
486 if (dotl) PenDrawClipped(pt[0], clipRect); |
|
487 if (dotr) PenDrawClipped(pt[1], clipRect); |
|
488 if (dobl) PenDrawClipped(pt[2], clipRect); |
|
489 if (dobr) PenDrawClipped(pt[3], clipRect); |
|
490 iDotParam+=iDotDirection; |
|
491 } |
|
492 if (pt[0].iY==pt[2].iY) |
|
493 { |
|
494 if (dotl) PenDrawClipped(pt[0], clipRect); |
|
495 if (dotr) PenDrawClipped(pt[1], clipRect); |
|
496 } |
|
497 if (aPie) |
|
498 { |
|
499 TPoint temp; |
|
500 const TPoint center = aRect.Center(); |
|
501 TLinearDDA line; |
|
502 line.Construct(arc.iStart,center); |
|
503 line.SingleStep(temp); |
|
504 while(!line.SingleStep(temp)) |
|
505 { |
|
506 PenDrawClipped(temp, clipRect); |
|
507 iDotParam+=iDotDirection; |
|
508 } |
|
509 line.Construct(arc.iEnd,center); |
|
510 line.SingleStep(temp); |
|
511 while(!line.SingleStep(temp)) |
|
512 { |
|
513 PenDrawClipped(temp, clipRect); |
|
514 iDotParam+=iDotDirection; |
|
515 } |
|
516 PenDrawClipped(center, clipRect); |
|
517 } |
|
518 iDrawDevice->UpdateRegion(clipRect); |
|
519 } |
|
520 iDotParam=dotparam; |
|
521 } |
|
522 |
|
523 /** |
|
524 Fills a pie. |
|
525 |
|
526 @param aRect The bounding rectangle. |
|
527 @param aStart The arc start point. |
|
528 @param aEnd The arc end point. |
|
529 @param aStartQuad The quadrant which contains aStart. |
|
530 @param aEndQuad The quadrant which contains aEnd. |
|
531 @param aQuads An array of full quadrants to fill. |
|
532 @see CSwDirectGdiEngine::DrawPie |
|
533 @see CSwDirectGdiEngine::AnalyseEllipse |
|
534 */ |
|
535 void CSwDirectGdiEngine::PieFill(const TRect& aRect, const TPoint& aStart, const TPoint& aEnd, |
|
536 TInt aStartQuad, TInt aEndQuad, const TBool* aQuads) |
|
537 { |
|
538 // arc runs counterclockwise, from startradius-center/ellipse intersect to endradius-center/ellipse intersect |
|
539 const TInt limit = iDefaultRegionPtr->Count(); |
|
540 TRect clipRect(0,0,0,0); |
|
541 for(TInt count=0;count<limit;count++) |
|
542 { |
|
543 clipRect=(*iDefaultRegionPtr)[count]; |
|
544 if (!clipRect.Intersects(aRect)) |
|
545 { |
|
546 continue; |
|
547 } |
|
548 clipRect.Intersection(aRect); |
|
549 if (!aQuads[0]) |
|
550 { |
|
551 PieShell(aRect, aStart, aEnd, aQuads, aStartQuad, aEndQuad, clipRect); |
|
552 } |
|
553 else |
|
554 { |
|
555 PieSliver(aRect, aStart, aEnd, aStartQuad, clipRect); |
|
556 } |
|
557 iDrawDevice->UpdateRegion(clipRect); |
|
558 } |
|
559 } |
|
560 |
|
561 /** |
|
562 Draws a pie spanning one or more quadrants. |
|
563 |
|
564 @param aRect The bounding rectangle. |
|
565 @param aStart The arc start point. |
|
566 @param aEnd The arc end point. |
|
567 @param aQuads Array of full quadrants to fill. |
|
568 @param aStartQuad The quadrant which contains aStart. |
|
569 @param aEndQuad The quadrant which contains aEnd. |
|
570 @param aClipRect The rectangle to which the pie is clipped. |
|
571 */ |
|
572 void CSwDirectGdiEngine::PieShell(const TRect& aRect,const TPoint& aStart, |
|
573 const TPoint& aEnd, const TBool* aQuads, TInt aStartQuad, |
|
574 TInt aEndQuad, TRect aClipRect) |
|
575 { |
|
576 TSwDirectGdiEllipse ellipse; |
|
577 ellipse.Construct(aRect); |
|
578 TInt c=aRect.Center().iX; |
|
579 TPoint pt[4]; |
|
580 TPoint tl,tr,bl,br; |
|
581 TBool donestart=EFalse; |
|
582 TBool doneend=EFalse; |
|
583 TBool todostart=EFalse; |
|
584 TBool todoend=EFalse; |
|
585 while(!ellipse.NextStep(pt[0],pt[1],pt[2],pt[3])) |
|
586 { |
|
587 if (pt[aStartQuad].iY==aStart.iY) |
|
588 todostart=ETrue; |
|
589 if (pt[aEndQuad].iY==aEnd.iY) |
|
590 todoend=ETrue; |
|
591 pt[0].iX++; |
|
592 pt[1].iX--; |
|
593 pt[2].iX++; |
|
594 pt[3].iX--; |
|
595 tl.iY=pt[0].iY; |
|
596 tr.iY=pt[1].iY; |
|
597 bl.iY=pt[2].iY; |
|
598 br.iY=pt[3].iY; |
|
599 if (aQuads[1] || (aEndQuad==0 && !doneend)) // tl quadrant, half top end chord |
|
600 tl.iX=pt[0].iX; |
|
601 else tl.iX=c+1; |
|
602 if (aQuads[2] || (aStartQuad==1 && !donestart)) // tr quadrant, half top start chord |
|
603 tr.iX=pt[1].iX; |
|
604 else tr.iX=c; |
|
605 if (aQuads[3] || (aStartQuad==2 && !donestart)) // bl quadrant, half top start chord |
|
606 bl.iX=pt[2].iX; |
|
607 else bl.iX=c+1; |
|
608 if (aQuads[4] || (aEndQuad==3 && !doneend)) // br quadrant, half top end chord |
|
609 br.iX=pt[3].iX; |
|
610 else br.iX=c; |
|
611 ClipFillLine(tl,tr,aClipRect); |
|
612 ClipFillLine(bl,br,aClipRect); |
|
613 // do partial quadrants |
|
614 if (todostart) |
|
615 { |
|
616 if (aStartQuad==0) |
|
617 { |
|
618 tl.iX=pt[0].iX; |
|
619 tr.iX=aStart.iX; |
|
620 ClipFillLine(tl,tr,aClipRect); |
|
621 } |
|
622 else if (aStartQuad==3) |
|
623 { |
|
624 bl.iX=aStart.iX; |
|
625 br.iX=pt[3].iX; |
|
626 ClipFillLine(bl,br,aClipRect); |
|
627 } |
|
628 } |
|
629 if (todoend) |
|
630 { |
|
631 if (aEndQuad==2) |
|
632 { |
|
633 bl.iX=pt[2].iX; |
|
634 br.iX=aEnd.iX; |
|
635 ClipFillLine(bl,br,aClipRect); |
|
636 } |
|
637 else if (aEndQuad==1) |
|
638 { |
|
639 tl.iX=aEnd.iX; |
|
640 tr.iX=pt[1].iX; |
|
641 ClipFillLine(tl,tr,aClipRect); |
|
642 } |
|
643 } |
|
644 donestart=todostart; |
|
645 doneend=todoend; |
|
646 } |
|
647 tl.iX=c+1; |
|
648 tr.iX=c; |
|
649 if (pt[0].iY==pt[2].iY) // congruent mid lines |
|
650 { |
|
651 if (pt[aStartQuad].iY==aStart.iY) |
|
652 todostart=ETrue; |
|
653 if (pt[aEndQuad].iY==aEnd.iY) |
|
654 todoend=ETrue; |
|
655 pt[0].iX++; |
|
656 pt[1].iX--; |
|
657 tl.iY=pt[0].iY; |
|
658 tr.iY=tl.iY; |
|
659 TBool leftflag=EFalse; |
|
660 TBool rightflag=EFalse; |
|
661 if (aQuads[1] || (aEndQuad==0 && !doneend) || |
|
662 aQuads[3] || (aStartQuad==2 && !donestart) || |
|
663 (todostart && aStartQuad==0) || (todoend && aEndQuad==2)) |
|
664 leftflag=ETrue; |
|
665 if (aQuads[2] || (aStartQuad==1 && !donestart) || |
|
666 aQuads[4] || (aEndQuad==3 && !doneend) || |
|
667 (todostart && aStartQuad==3) || (todoend && aEndQuad==1)) |
|
668 rightflag=ETrue; |
|
669 if (leftflag) tl.iX=pt[0].iX; |
|
670 if (rightflag) tr.iX=pt[1].iX; |
|
671 ClipFillLine(tl,tr,aClipRect); |
|
672 } |
|
673 else |
|
674 { |
|
675 tl.iY=aRect.Center().iY; |
|
676 tr.iY=tl.iY; |
|
677 if (aStartQuad==3) tr.iX=aStart.iX-1; |
|
678 if (aEndQuad==2) tl.iX=aEnd.iX+1; |
|
679 ClipFillLine(tl,tr,aClipRect); |
|
680 } |
|
681 PieTriangles(aStartQuad==1 || aStartQuad==2,aStart,aRect.Center(), aClipRect); |
|
682 PieTriangles(aEndQuad==0 || aEndQuad==3,aEnd,aRect.Center(), aClipRect); |
|
683 } |
|
684 |
|
685 /** |
|
686 Draws a filled triangle which forms part of a partially filled quadrant. |
|
687 |
|
688 @param aInside A boolean value indicating which side of the line to fill. |
|
689 @param aStart The start of the line which forms the hypotenuse of the triangle. |
|
690 @param aEnd The end of the line which forms the hypotenuse of the triangle. |
|
691 @param aClipRect The rectangle to which the pie is clipped. |
|
692 @see CSwDirectGdiEngine::PieShell |
|
693 */ |
|
694 void CSwDirectGdiEngine::PieTriangles(TBool aInside,const TPoint& aStart,const TPoint& aEnd, TRect aClipRect) |
|
695 { |
|
696 TInt x=aInside?aEnd.iX:aStart.iX; |
|
697 if (aStart.iX>aEnd.iX) |
|
698 { |
|
699 if (aInside) |
|
700 { |
|
701 x++; |
|
702 } |
|
703 else |
|
704 { |
|
705 x--; |
|
706 } |
|
707 } |
|
708 else |
|
709 { |
|
710 if (!aInside) |
|
711 { |
|
712 x++; |
|
713 } |
|
714 } |
|
715 TLinearDDA line; |
|
716 TPoint pt,left,right; |
|
717 line.Construct(aStart,aEnd); |
|
718 line.NextStep(pt); |
|
719 while(!line.NextStep(pt)) |
|
720 { |
|
721 if (pt.iY==aEnd.iY) break; |
|
722 left.iX=Min(pt.iX,x); |
|
723 right.iX=Max(pt.iX,x); |
|
724 left.iY=right.iY=pt.iY; |
|
725 ClipFillLine(left,right,aClipRect); |
|
726 } |
|
727 } |
|
728 |
|
729 /** |
|
730 Draws a pie entirely contained in one quadrant. |
|
731 |
|
732 @param aRect The rectangle in which to draw the ellipse. |
|
733 @param aStart The arc start point. |
|
734 @param aEnd The arc end point. |
|
735 @param aQuad The quadrant containing the pie. |
|
736 @param aClipRect The rectangle to which the pie is clipped. |
|
737 */ |
|
738 void CSwDirectGdiEngine::PieSliver(const TRect& aRect,const TPoint& aStart, |
|
739 const TPoint& aEnd, TInt aQuad, TRect aClipRect) |
|
740 { |
|
741 TPoint center=aRect.Center(),left,right; |
|
742 TPoint nearinter(aStart),farinter(aEnd); |
|
743 if (Abs(nearinter.iY-center.iY)>Abs(farinter.iY-center.iY)) |
|
744 { |
|
745 nearinter=aEnd; |
|
746 farinter=aStart; |
|
747 } |
|
748 TBool ellipseComplete = EFalse; |
|
749 TPoint pt[4]; |
|
750 TSwDirectGdiEllipse ellipse; |
|
751 ellipse.Construct(aRect); |
|
752 TLinearDDA mainline; |
|
753 mainline.Construct(farinter,center); |
|
754 ellipseComplete = ellipse.SingleStep(pt[0],pt[1],pt[2],pt[3]); |
|
755 mainline.SingleStep(right); |
|
756 do { |
|
757 while(!ellipseComplete && pt[aQuad].iY!=right.iY) |
|
758 ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]); |
|
759 left=pt[aQuad]; |
|
760 while(!ellipseComplete && pt[aQuad].iY==right.iY) |
|
761 { |
|
762 left=pt[aQuad]; |
|
763 ellipseComplete = ellipse.NextStep(pt[0],pt[1],pt[2],pt[3]); |
|
764 } |
|
765 if (right.iY==nearinter.iY || (ellipseComplete && (pt[0].iY != pt[2].iY))) |
|
766 break; |
|
767 if (left.iX>right.iX) |
|
768 { |
|
769 TInt temp=left.iX; |
|
770 left.iX=right.iX; |
|
771 right.iX=temp; |
|
772 } |
|
773 if(right==farinter && left.iX<=right.iX) |
|
774 { |
|
775 continue; |
|
776 } |
|
777 left.iX++; |
|
778 right.iX--; |
|
779 if (left.iX<=right.iX) |
|
780 ClipFillLine(left,right,aClipRect); |
|
781 } |
|
782 while(!mainline.NextStep(right)); |
|
783 TPoint temppt; |
|
784 TLinearDDA line; |
|
785 line.Construct(nearinter,center); |
|
786 TBool linestat=EFalse; |
|
787 do |
|
788 linestat=line.SingleStep(temppt); |
|
789 while(temppt.iY!=right.iY && !linestat); |
|
790 do { |
|
791 do { |
|
792 left=temppt; |
|
793 linestat=line.SingleStep(temppt); |
|
794 } |
|
795 while(temppt.iY==right.iY && !linestat); |
|
796 if (ellipseComplete) |
|
797 break; |
|
798 if (left.iX>right.iX) |
|
799 { |
|
800 TInt temp=left.iX; |
|
801 left.iX=right.iX; |
|
802 right.iX=temp; |
|
803 } |
|
804 if(right==farinter && left.iX<=right.iX) |
|
805 { |
|
806 continue; |
|
807 } |
|
808 left.iX++; |
|
809 right.iX--; |
|
810 if (left.iX<=right.iX) |
|
811 ClipFillLine(left,right,aClipRect); |
|
812 } |
|
813 while(!mainline.NextStep(right)); |
|
814 } |
|
815 |