First public contribution.
1 // Copyright (c) 1998-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.
24 EXPORT_C TLinearDDA::TLinearDDA():
33 iBoundingRectSet(EFalse),
37 /** Constructs the default linear DDA.
39 No start or end point is defined for the line. */
43 EXPORT_C TLinearDDA::TLinearDDA(const TLinearDDA& aLine):
45 iDifference(aLine.iDifference),
46 iFinish(aLine.iFinish),
47 iGradient(aLine.iGradient),
51 iBoundingRect(aLine.iBoundingRect),
52 iBoundingRectSet(aLine.iBoundingRectSet),
53 iInsideX(aLine.iInsideX),
54 iInsideY(aLine.iInsideY),
55 iStatus(aLine.iStatus)
56 /** Copy constructs a linear DDA from the specified linear DDA.
58 @param aLine The linear DDA to be copied. */
62 EXPORT_C void TLinearDDA::Construct(const TPoint& aStart,const TPoint& aFinish,TLineMode aMode)
63 /** Constructs a linear DDA, setting the start and end points of the line.
65 @param aStart The start point of the line.
66 @param aFinish The end point of the line.
67 @param aMode The mode of the line; defaults to centred. */
71 iDifference=(iFinish-iStart).AsSize();
72 iDifference.iWidth=Abs(iDifference.iWidth);
73 iDifference.iHeight=Abs(iDifference.iHeight);
74 iInc.iX=(iStart.iX>iFinish.iX)?-1:1;
75 iInc.iY=(iStart.iY>iFinish.iY)?-1:1;
76 if(iDifference.iWidth)
77 iGradient=(iFinish.iY-iStart.iY)/(iFinish.iX-iStart.iX);
80 iCount=iDifference.iWidth;
82 iCount=iDifference.iHeight;
91 iBoundingRectSet=EFalse;
97 EXPORT_C TBool TLinearDDA::SingleStep(TPoint& aPosition)
98 /** Gets the pixel co-ordinates of the next pixel on the pixel line.
100 The function is called repeatedly until the whole line has been traversed or,
101 if JumpToRect() has been called, until the part of the line inside the rectangle
102 has been traversed. Note that, for performance reasons, JumpToRect() may fail
103 to detect the intersection of the line with the rectangle accurately and
104 SingleStep() may return more points than strictly necessary.
106 @param aPosition On entry to the first call, this can be a reference to any
107 point. On return from the first call, this is the position of the first pixel
108 in the line, as specified during construction of this object. On return from
109 subsequent calls, this is the position of subsequent pixels in the line, as
110 calculated by the function. On return from the final call, this is the position
111 of the last pixel in the line, as specified during construction of this object.
112 @return ETrue, when the position of the last pixel is returned; EFalse,
122 if (iDifference.iHeight == 0) // horizontal line
125 if (iPos.iX == iFinish.iX)
130 else if (iDifference.iWidth == 0) // vertical line
133 if (iPos.iY == iFinish.iY)
138 else // diagonal stripes
142 iCount -= iDifference.iHeight;
146 iCount += iDifference.iWidth;
152 iCount -= iDifference.iWidth;
156 iCount += iDifference.iHeight;
160 if ((iPos.iX == iFinish.iX) && (iPos.iY == iFinish.iY))
167 if (iStatus == EComplete)
173 if (iPos.iX >= iBoundingRect.iTl.iX && iPos.iX < iBoundingRect.iBr.iX)
181 if (iPos.iY >= iBoundingRect.iTl.iY && iPos.iY < iBoundingRect.iBr.iY)
197 EXPORT_C TBool TLinearDDA::NextStep(TPoint& aPosition)
198 /** Gets the pixel co-ordinates of the start of the next scan line.
200 The best line that joins the start and end points is formed from all the scan
201 lines returned by this function.
203 The function is called repeatedly until the start position of all scanlines
206 The start and end points passed to the constructor of this object define the
207 boundaries of the line. Successive scan lines move from the start point to
210 @param aPosition On entry to the first call, this can be a reference to any
211 point. On return from the first call, this is the position of the pixel that
212 defines the leftmost position of the first scan line. On return from subsequent
213 calls, this is the position of the pixel that defines the leftmost position
214 of the next scan line. On return from the final call, this is the position
215 of the last pixel in the line, as specified during construction.
216 @return ETrue, when the position of the last pixel is returned; EFalse,
219 if (!iDifference.iHeight) // horizontal line
226 if (!iDifference.iWidth || iGradient || (iStatus != ECurrent))
228 return SingleStep(aPosition);
230 // !iGradient && (iStatus != EInitialised)
233 while ((iCount - iDifference.iHeight) >= 0)
235 if (SingleStep(aPosition))
238 return SingleStep(aPosition);
240 // faster version avoids function calls
241 TBool lastLoop = EFalse;
243 if ((iCount - iDifference.iHeight) < 0)
247 iCount -= iDifference.iHeight;
251 iCount += iDifference.iWidth;
255 if ((iPos.iX == iFinish.iX) && (iPos.iY == iFinish.iY))
267 EXPORT_C TBool TLinearDDA::SingleScanline(TPoint& aStartPosition,TPoint& aEndPosition)
268 /** Gets the start and end pixel co-ordinates that define the next scan line.
270 The best line that joins the start and end points is formed from all the scan
271 lines returned by this function.
273 The function is called repeatedly until the position of all scanlines has
276 The start and end points passed to the constructor of this object define the
277 boundaries of the line. Successive scan lines move from the start point to
280 @param aStartPosition On entry to the first call, this can be a reference
281 to any point. On return from the first call, this is the position of the pixel
282 that defines the leftmost position of the first scan line. On return from
283 subsequent calls, this is the position of the pixel that defines the leftmost
284 position of the next scan line. On return from the final call, either this
285 or aEndPosition is set to the end point, as specified during construction.
286 @param aEndPosition On entry to the first call, this can be a reference to
287 any point. On return from the first call, this is the position of the pixel
288 that defines the rightmost position of the first scan line. On return from
289 subsequent calls, this is the position of the pixel that defines the rightmost
290 position of the next scan line. On return from the final call, either this
291 or aStartPosition is set to the end point, as specified during construction.
292 @return ETrue, when the position of the last scan line includes the end point;
293 EFalse, otherwise. */
296 if(iDifference.iHeight==0)
298 aStartPosition=iStart;
299 aEndPosition=iFinish;
302 if(iDifference.iWidth==0 || iGradient)
304 done=SingleStep(aStartPosition);
305 aEndPosition=aStartPosition;
309 done=SingleStep(aStartPosition);
310 aEndPosition=aStartPosition;
311 while(iCount-iDifference.iHeight>=0 && !done)
313 iCount -= iDifference.iHeight;
317 iCount += iDifference.iWidth;
321 if ((iPos.iX == iFinish.iX) && (iPos.iY == iFinish.iY))
331 EXPORT_C void TLinearDDA::JumpToRect(const TRect& aRect)
332 /** Jumps to start of a clipping rectangle.
334 This will accelerate the linear DDA to the vicinity of the specified rectangle.
335 It is NOT guaranteed to reach the rectangle, but will reduce co-ordinates
336 that are 1000's out to co-ordinates that are 10's out. Because of this, failure
337 to intersect the rectangle may not be detected. If it is, or the line has
338 not been constructed or has been run to completion, then a subsequent call
339 to the stepping functions returns ETrue.
341 @param aRect The rectangle to be jumped to. */
343 if(aRect.IsEmpty() || iStatus!=EInitialised) return;
345 iBoundingRectSet=ETrue;
348 if (iStart.iX < aRect.iTl.iX)
349 nearestx = aRect.iTl.iX;
350 else if (iStart.iX >= aRect.iBr.iX)
351 nearestx = aRect.iBr.iX;
355 if (iStart.iY < aRect.iTl.iY)
356 nearesty = aRect.iTl.iY;
357 else if (iStart.iY >= aRect.iBr.iY)
358 nearesty = aRect.iBr.iY;
361 if (iInsideX && iInsideY)
369 JumpToXCoord(nearestx,dummy);
375 JumpToYCoord(dummy,nearesty);
380 EXPORT_C void TLinearDDA::JumpToXCoord(const TInt aXCoord,TInt& aYCoord)
381 /** Jumps to x co-ordinate.
383 The other co-ordinate of the intersection is returned through a reference
384 argument. After a jump call, the line is ready to continue through calls to
385 the stepping functions.
387 This function accelerates the Linear DDA stepping functions (e.g. SingleStep())
388 making them return EFalse when they reach the specified co-ordinate. If the
389 line does not cross the co-ordinate, has not been constructed, has been run
390 to completion or the intersection is the end point of the line then the stepping
391 functions will return ETrue.
393 @param aXCoord x co-ordinate to jump to
394 @param aYCoord On return, this parameter holds the y co-ordinate which corresponds
395 to the specified x co-ordinate */
397 if(iStatus==EComplete) return; // not constructed
398 if((iStart.iX<aXCoord && iFinish.iX<aXCoord) || (iStart.iX>aXCoord && iFinish.iX>aXCoord))
399 return; // no intersection
401 if(iStart.iX==aXCoord) return; // trivial first intersection
403 if(iDifference.iHeight==0) // horizontal line
409 TInt64 numsteps=Abs(aXCoord-iPos.iX);
410 TInt64 tempcount=TInt64(iCount)-(TInt64(iDifference.iHeight)*numsteps);
411 numsteps=Abs(tempcount/iDifference.iWidth);
412 tempcount+=numsteps*iDifference.iWidth;
415 tempcount+=iDifference.iWidth;
418 iCount = I64INT(tempcount);
419 iPos.iY += (iInc.iY * I64INT(numsteps));
425 while(iPos.iX!=aXCoord)
427 iCount-=iDifference.iWidth;
430 iCount+=iDifference.iHeight;
438 if ((iPos.iX == iFinish.iX) && (iPos.iY == iFinish.iY))
445 EXPORT_C void TLinearDDA::JumpToYCoord(TInt& aXCoord,const TInt aYCoord)
446 /** Jumps to a y co-ordinate.
448 The other co-ordinate of the intersection is returned through a reference
449 argument. After a jump call, the line is ready to continue through calls to
450 the stepping functions.
452 This function accelerates the Linear DDA stepping functions (e.g. SingleStep())
453 making them return EFalse when they reach the specified co-ordinate. If the
454 line does not cross the co-ordinate, has not been constructed, has been run
455 to completion or the intersection is the end point of the line then they will
458 @param aXCoord On return, this parameter holds the x co-ordinate which corresponds
459 to the specified y co-ordinate.
460 @param aYCoord y co-ordinate to jump to */
462 if(iStatus==EComplete) return; // not constructed
463 if((iStart.iY<aYCoord && iFinish.iY<aYCoord) || (iStart.iY>aYCoord && iFinish.iY>aYCoord))
464 return; // no intersection
466 if(iStart.iY==aYCoord) return; // trivial first intersection
468 if(iDifference.iWidth==0) // vertical line
474 while(iPos.iY!=aYCoord)
476 iCount-=iDifference.iHeight;
479 iCount+=iDifference.iWidth;
488 TInt64 numsteps=Abs(aYCoord-iPos.iY);
489 TInt64 tempcount=TInt64(iCount)-(TInt64(iDifference.iWidth)*numsteps);
490 numsteps=Abs(tempcount/iDifference.iHeight);
491 tempcount+=numsteps*iDifference.iHeight;
494 tempcount+=iDifference.iHeight;
497 iCount = I64INT(tempcount);
498 iPos.iX += (iInc.iX * I64INT(numsteps));
503 if ((iPos.iX == iFinish.iX) && (iPos.iY == iFinish.iY))
509 void TLinearDDA::UpdatePosition()
513 EXPORT_C void TLinearDDA::JumpToXCoord2(TInt aXCoord,TInt& aYCoord)
515 Jumps to x co-ordinate.
517 This works in the same way as TLinearDDA::JumpToXCoord except that it make sure
518 that using the NextStep function does not return the same value twice.
520 @param aXCoord x co-ordinate to jump to
521 @param aYCoord On return, this parameter holds the y co-ordinate which corresponds
522 to the specified x co-ordinate
523 @see TLinearDDA::JumpToXCoord(TInt, TInt&)
526 JumpToXCoord(aXCoord,aYCoord);
530 EXPORT_C void TLinearDDA::JumpToYCoord2(TInt& aXCoord,TInt aYCoord)
532 Jumps to a y co-ordinate.
534 This works in the same way as TLinearDDA::JumpToYCoord except that it make sure
535 that using the NextStep function does not return the same value twice.
537 @param aXCoord On return, this parameter holds the x co-ordinate which corresponds
538 to the specified y co-ordinate.
539 @param aYCoord y co-ordinate to jump to
540 @see TLinearDDA::JumpToYCoord(TInt&, TInt)
543 JumpToYCoord(aXCoord,aYCoord);