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>
21 #include "bitgcextradata.h"
24 /** Draws a straight line between two points.
26 The function provides a concrete implementation of the pure virtual
27 function CGraphicsContext::DrawLine(). The function
28 behaviour is the same as documented in that class. */
29 EXPORT_C void CFbsBitGc::DrawLine(const TPoint& aPt1,const TPoint& aPt2)
33 TRect lineBoundingRect(aPt1,aPt2);
34 lineBoundingRect.Normalize();
35 lineBoundingRect.Move(iOrigin);
36 lineBoundingRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1);
37 if(!lineBoundingRect.Intersects(iUserClipRect))
39 iLinePosition = aPt2;// if DrawLine returns due to aPt2 being outside of the clipping rect then subsequent line are drawn from correct point.
44 iDevice->DrawingBegin();
45 DoDrawLine(aPt1,aPt2,ETrue);
46 iDevice->DrawingEnd();
49 /** Draws a straight line from the current drawing point to a specified
52 The function provides a concrete implementation of the pure virtual
53 function CGraphicsContext::DrawLineTo(). The function
54 behaviour is the same as documented in that class. */
55 EXPORT_C void CFbsBitGc::DrawLineTo(const TPoint& aPoint)
57 DrawLine(iLinePosition,aPoint);
61 /** Draws a straight line relative to the current drawing point, using a
64 The function provides a concrete implementation of the pure virtual
65 function CGraphicsContext::DrawLineBy(). The function
66 behaviour is the same as documented in that class. */
67 EXPORT_C void CFbsBitGc::DrawLineBy(const TPoint& aVector)
69 DrawLine(iLinePosition,iLinePosition + aVector);
72 /** Draws a polyline from a set of points specified in a list.
74 The functions provides a concrete implementation of the pure virtual
75 functions CGraphicsContext::DrawPolyLine(). The function
76 behaviour is the same as documented in that class. */
77 EXPORT_C void CFbsBitGc::DrawPolyLine(const CArrayFix<TPoint>* aPointList)
79 if(!aPointList || iPenSize.iWidth < 1 || iPenSize.iHeight < 1)
82 const TInt vertexes = aPointList->Count()-1;
84 for (TInt count = 0; count < vertexes; count++)
85 DrawLine((*aPointList)[count],(*aPointList)[count + 1]);
87 if (iPenStyle == CGraphicsContext::ESolidPen && vertexes >= 0)
88 Plot((*aPointList)[vertexes]);
91 /** Draws a polyline from a set of points specified in an array, but does not draw
92 the final point of the last line.
94 @param aPointList An array containing the points on the polyline. */
95 EXPORT_C void CFbsBitGc::DrawPolyLineNoEndPoint(const CArrayFix<TPoint>* aPointList)
97 if(!aPointList || iPenSize.iWidth < 1 || iPenSize.iHeight < 1)
100 const TInt vertexes = aPointList->Count() - 1;
102 for (TInt count = 0; count < vertexes; count++)
103 DrawLine((*aPointList)[count],(*aPointList)[count + 1]);
106 /** Draws a polyline from a set of points specified in a list.
108 The functions provides a concrete implementation of the pure virtual
109 functions CGraphicsContext::DrawPolyLine(). The function
110 behaviour is the same as documented in that class. */
111 EXPORT_C void CFbsBitGc::DrawPolyLine(const TPoint* aPointList,TInt aNumPoints)
113 DrawPolyLineNoEndPoint(aPointList,aNumPoints);
115 if (iPenStyle == CGraphicsContext::ESolidPen)
116 Plot(aPointList[aNumPoints - 1]);
119 /** Draws a polyline from a set of points specified in a list, but does not
120 draw the final point of the last line.
122 @param aPointList Pointer to a set of points on the polyline.
123 @param aNumPoints Number of points in the list. */
124 EXPORT_C void CFbsBitGc::DrawPolyLineNoEndPoint(const TPoint* aPointList,TInt aNumPoints)
126 if (!aPointList || iPenSize.iWidth < 1 || iPenSize.iHeight < 1)
129 const TInt vertexes = aNumPoints - 1;
131 for (TInt count = 0; count < vertexes; count++)
132 DrawLine(aPointList[count],aPointList[count + 1]);
135 /** Draws and fills a polygon defined using a list of points.
137 The function provides a concrete implementation of the pure virtual
138 function CGraphicsContext::DrawPolygon(). The function
139 behaviour is the same as documented in that class. */
140 EXPORT_C TInt CFbsBitGc::DrawPolygon(const CArrayFix<TPoint>* aPointList,TFillRule aFillRule)
147 const TInt numpoints = aPointList->Count();
150 return KErrNone; // Nothing to do!
153 iDevice->DrawingBegin(&iBrushBitmap);
154 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
156 if (iBrushStyle != ENullBrush)
158 TRect pointrect(0,0,0,0);
159 TRect truncrect(0,0,0,0);
160 TBool largepolygon = EFalse;
162 for (TInt count = 0; count < numpoints; count++)
164 pointrect.iTl = (*aPointList)[count] + iOrigin;
165 truncrect.iTl = pointrect.iTl;
166 iDevice->TruncateRect(truncrect);
168 if (pointrect.iTl != truncrect.iTl)
170 largepolygon = ETrue;
176 PolyFillLarge(aPointList,aFillRule);
178 PolyFill(aPointList,aFillRule);
181 if (iPenStyle != ENullPen)
182 if (iPenSize.iWidth > 0 && iPenSize.iHeight > 0)
183 PolyOutline(aPointList);
187 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
189 iDevice->DrawingEnd(&iBrushBitmap);
195 /** Draws and fills a polygon defined using a list of points.
197 The function provides a concrete implementation of the pure virtual
198 function CGraphicsContext::DrawPolygon(). The function
199 behaviour is the same as documented in that class. */
200 EXPORT_C TInt CFbsBitGc::DrawPolygon(const TPoint* aPointList,
202 CGraphicsContext::TFillRule aFillRule)
206 if (!aPointList || aNumPoints < 0)
210 return KErrNone; // Nothing to do!
213 iDevice->DrawingBegin(&iBrushBitmap);
214 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
216 if (iBrushStyle != ENullBrush)
218 TRect pointrect(0,0,0,0);
219 TRect truncrect(0,0,0,0);
220 TBool largepolygon = EFalse;
222 for (TInt count = 0; count < aNumPoints; count++)
224 pointrect.iTl = aPointList[count] + iOrigin;
225 truncrect.iTl = pointrect.iTl;
226 iDevice->TruncateRect(truncrect);
228 if (pointrect.iTl != truncrect.iTl)
230 largepolygon = ETrue;
236 PolyFillLarge(aPointList,aNumPoints,aFillRule);
238 PolyFill(aPointList,aNumPoints,aFillRule);
241 if (iPenStyle != ENullPen && iPenSize.iWidth > 0 && iPenSize.iHeight > 0)
242 PolyOutline(aPointList,aNumPoints);
246 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
248 iDevice->DrawingEnd(&iBrushBitmap);
253 void CFbsBitGc::DoDrawLine(TPoint aPt1,TPoint aPt2,TBool aDrawStartPoint)
255 iLinePosition = aPt2;
257 if (aPt1 == aPt2 || iPenStyle == ENullPen || !iPenSize.iWidth || !iPenSize.iHeight)
263 TRect temp(aPt1,aPt2);
265 temp.Grow(iPenSize.iWidth,iPenSize.iHeight);
267 if (UserClipRect(temp))
270 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
273 drawDevice->GetDrawRect(screenRect);
274 screenRect.Grow(iPenSize.iWidth,iPenSize.iHeight);
276 const TInt dotParam = iDotParam;
279 for (TInt count = 0; count < iDefaultRegionPtr->Count(); count++)
281 iDotParam = dotParam;
282 iClipRect = (*iDefaultRegionPtr)[count];
284 if (!iClipRect.Intersects(temp))
287 line.Construct(aPt1,aPt2);
288 line.JumpToRect(screenRect);
289 if (iPenStyle != ESolidPen)
290 while (!line.SingleStep(plotpt))
291 iDotParam += iDotDirection;
295 iClipRect.Intersection(temp);
297 if ((iPenSize.iWidth > 1 || iPenSize.iHeight > 1) && iPenStyle == ESolidPen) // wide solid line
298 DoDrawSolidWideLine(aPt1,aPt2,aDrawStartPoint,screenRect);
299 else if (iPenSize.iWidth > 1 || iPenSize.iHeight > 1) // dotted line
300 DoDrawDottedWideLine(aPt1,aPt2,aDrawStartPoint,screenRect);
301 else if (iPenStyle != ESolidPen) // single pixel dotted line
304 line.Construct(aPt1,aPt2);
305 line.JumpToRect(screenRect);
307 iDotParam = dotParam;
308 if (!aDrawStartPoint)
310 line.SingleStep(plotpt);
311 iDotParam += iDotDirection;
314 while (!line.SingleStep(plotpt))
316 PenDrawClipped(plotpt);
317 iDotParam += iDotDirection;
320 else if (aPt1.iY == aPt2.iY &&
321 (aPt1.iY >= iClipRect.iTl.iY && aPt1.iY < iClipRect.iBr.iY))
322 { // single pixel solid horizontal line
323 TInt start = Min(aPt1.iX,aPt2.iX + 1);
324 TInt length = Abs(aPt2.iX - aPt1.iX);
326 if (!aDrawStartPoint)
327 if (aPt1.iX < aPt2.iX)
331 if (start < iClipRect.iTl.iX)
333 length += start - iClipRect.iTl.iX;
334 start = iClipRect.iTl.iX;
336 if (start + length > iClipRect.iBr.iX)
337 length = iClipRect.iBr.iX - start;
341 BG_ASSERT_DEBUG(start >= iUserClipRect.iTl.iX,EBitgdiPanicOutOfBounds);
342 BG_ASSERT_DEBUG(aPt1.iY >= iUserClipRect.iTl.iY,EBitgdiPanicOutOfBounds);
343 BG_ASSERT_DEBUG(start + length <= iUserClipRect.iBr.iX,EBitgdiPanicOutOfBounds);
344 BG_ASSERT_DEBUG(aPt1.iY < iUserClipRect.iBr.iY,EBitgdiPanicOutOfBounds);
346 drawDevice->WriteRgbMulti(start,aPt1.iY,length,1,iPenColor,iDrawMode);
349 else if (aPt1.iX == aPt2.iX && (aPt1.iX >= iClipRect.iTl.iX && aPt1.iX < iClipRect.iBr.iX))
350 { // single pixel solid vertical line
351 TInt start = Min(aPt1.iY,aPt2.iY + 1);
352 TInt length = Abs(aPt2.iY - aPt1.iY);
354 if (!aDrawStartPoint)
355 if (aPt1.iY < aPt2.iY)
360 if (start < iClipRect.iTl.iY)
362 length += start - iClipRect.iTl.iY;
363 start = iClipRect.iTl.iY;
365 if (start + length > iClipRect.iBr.iY)
366 length = iClipRect.iBr.iY - start;
370 BG_ASSERT_DEBUG(aPt1.iX >= iUserClipRect.iTl.iX,EBitgdiPanicOutOfBounds);
371 BG_ASSERT_DEBUG(start >= iUserClipRect.iTl.iY,EBitgdiPanicOutOfBounds);
372 BG_ASSERT_DEBUG(aPt1.iX < iUserClipRect.iBr.iX,EBitgdiPanicOutOfBounds);
373 BG_ASSERT_DEBUG(start + length <= iUserClipRect.iBr.iY,EBitgdiPanicOutOfBounds);
375 drawDevice->WriteRgbMulti(aPt1.iX,start,1,length,iPenColor,iDrawMode);
379 { // single pixel solid diagonal line
381 line.Construct(aPt1,aPt2);
383 line.JumpToRect(screenRect);
385 if (!aDrawStartPoint)
386 line.SingleStep(plotpt);
388 while (!line.SingleStep(plotpt))
390 if (iClipRect.Contains(plotpt))
392 BG_ASSERT_DEBUG(plotpt.iX >= iUserClipRect.iTl.iX,EBitgdiPanicOutOfBounds);
393 BG_ASSERT_DEBUG(plotpt.iY >= iUserClipRect.iTl.iY,EBitgdiPanicOutOfBounds);
394 BG_ASSERT_DEBUG(plotpt.iX < iUserClipRect.iBr.iX,EBitgdiPanicOutOfBounds);
395 BG_ASSERT_DEBUG(plotpt.iY < iUserClipRect.iBr.iY,EBitgdiPanicOutOfBounds);
397 drawDevice->WriteRgb(plotpt.iX,plotpt.iY,iPenColor,iDrawMode);
402 drawDevice->UpdateRegion(iClipRect);
406 void CFbsBitGc::DoDrawSolidWideLine(const TPoint& aPt1,
408 TBool aDrawStartPoint,
409 const TRect& aScreenRect)
411 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
414 line.Construct(aPt1,aPt2);
417 line.JumpToRect(aScreenRect);
418 if (!aScreenRect.Contains(plotpt) || !aDrawStartPoint)
419 line.SingleStep(plotpt);
421 TInt* deferred = NULL;
422 const TInt doubleheight = iPenSize.iHeight << 1;
424 if (iFbsBitGcExtraData->PenArray())
425 deferred = new TInt[doubleheight];
427 if (!iFbsBitGcExtraData->PenArray() || !deferred)
429 while (!line.SingleStep(plotpt))
430 PenDrawClipped(plotpt);
434 const TBool down = (aPt2.iY >= aPt1.iY);
436 for (TInt fillcount = 0; fillcount < doubleheight; )
438 deferred[fillcount++] = KMaxTInt;
439 deferred[fillcount++] = KMinTInt;
443 TInt nexty = plotpt.iY;
445 nexty -= ((iPenSize.iHeight - 1) >> 1);
447 nexty += (iPenSize.iHeight >> 1);
449 TInt lasty = plotpt.iY;
451 while (!line.SingleStep(plotpt))
453 if (plotpt.iY != lasty)
455 if (nexty >= iClipRect.iTl.iY && nexty < iClipRect.iBr.iY)
457 TInt left = deferred[nextline];
458 TInt right = deferred[nextline + 1];
459 if (left < iClipRect.iTl.iX)
460 left = iClipRect.iTl.iX;
461 if (right >= iClipRect.iBr.iX)
462 right = iClipRect.iBr.iX - 1;
465 drawDevice->WriteRgbMulti(left,nexty,right - left + 1,1,iPenColor,CGraphicsContext::EDrawModePEN);
473 deferred[nextline++] = KMaxTInt;
474 deferred[nextline++] = KMinTInt;
475 if (nextline == doubleheight)
479 PenDrawDeferred(plotpt,deferred,nextline);
482 for (TInt restofline = 0; restofline < doubleheight; restofline += 2,nextline += 2)
484 if (nextline == doubleheight)
487 if (nexty >= iClipRect.iTl.iY && nexty < iClipRect.iBr.iY)
489 TInt left = deferred[nextline];
490 TInt right = deferred[nextline+1];
491 if (left < iClipRect.iTl.iX)
492 left = iClipRect.iTl.iX;
493 if (right >= iClipRect.iBr.iX)
494 right = iClipRect.iBr.iX-1;
497 drawDevice->WriteRgbMulti(left,nexty,right - left + 1,1,iPenColor,CGraphicsContext::EDrawModePEN);
511 void CFbsBitGc::DoDrawDottedWideLine(const TPoint& aPt1,
513 TBool aDrawStartPoint,
514 const TRect& aScreenRect)
517 line.Construct(aPt1,aPt2);
520 line.JumpToRect(aScreenRect);
521 if (!aDrawStartPoint)
523 line.SingleStep(plotpt);
524 iDotParam += iDotDirection;
527 const TInt maxdim = Max(iPenSize.iWidth,iPenSize.iHeight);
532 while (!done && !(iDotMask & (1 << ((iDotParam / maxdim) % iDotLength))))
534 done = line.SingleStep(plotpt);
535 iDotParam += iDotDirection;
538 TPoint startdash(plotpt);
539 TPoint enddash(plotpt);
541 while (!done && (iDotMask & (1 << ((iDotParam / maxdim) % iDotLength))))
544 done = line.SingleStep(plotpt);
545 iDotParam += iDotDirection;
548 DoDrawSolidWideLine(startdash,enddash,ETrue,aScreenRect);
552 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
553 void CFbsBitGc::PolyFill(const CArrayFix<TPoint>* aPointList,TFillRule aFillRule)
560 const TInt limit = iDefaultRegionPtr->Count();
561 for (TInt count = 0; count < limit; count++)
563 iClipRect = (*iDefaultRegionPtr)[count];
565 if (UserClipRect(iClipRect))
568 CPolygonFiller polyfill;
569 polyfill.Construct(aPointList,aFillRule);
571 for(polyfill.GetNextPixelRun(exists,scanline,pixelRunStart,pixelRunEnd);exists;
572 polyfill.GetNextPixelRun(exists,scanline,pixelRunStart,pixelRunEnd))
574 TPoint start(pixelRunStart,scanline),end(pixelRunEnd,scanline);
577 ClipFillLine(start,end);
581 iDevice->iDrawDevice->UpdateRegion(iClipRect);
585 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
586 void CFbsBitGc::PolyFillLarge(const CArrayFix<TPoint>* aPointList,TFillRule aFillRule)
592 const TInt limit = iDefaultRegionPtr->Count();
593 for (TInt count = 0; count < limit; count++)
595 iClipRect = (*iDefaultRegionPtr)[count];
597 if (UserClipRect(iClipRect))
600 CPolygonFiller polyfill;
601 polyfill.Construct(aPointList,aFillRule,CPolygonFiller::EGetPixelRunsSequentiallyForSpecifiedScanLines);
602 TInt clipRectOffsetStart = iClipRect.iTl.iY - iOrigin.iY;
603 TInt clipRectOffsetEnd = iClipRect.iBr.iY - iOrigin.iY;
605 for (TInt scanline = clipRectOffsetStart; scanline < clipRectOffsetEnd; scanline++)
607 polyfill.GetNextPixelRunOnSpecifiedScanLine(exists,scanline,pixelRunStart,pixelRunEnd);
610 TPoint start(pixelRunStart,scanline),end(pixelRunEnd,scanline);
613 ClipFillLine(start,end);
614 polyfill.GetNextPixelRunOnSpecifiedScanLine(exists,scanline,pixelRunStart,pixelRunEnd);
619 iDevice->iDrawDevice->UpdateRegion(iClipRect);
623 void CFbsBitGc::PolyOutline(const CArrayFix<TPoint>* aPointList)
625 const TInt vertexes = aPointList->Count();
627 for (TInt count = 0; count < vertexes; count++)
629 TPoint point1((*aPointList)[count]);
630 TPoint point2((*aPointList)[(count + 1) % vertexes]);
632 if (point1.iY < point2.iY)
633 DoDrawLine(point1,point2,ETrue);
637 iDotParam += Max(Abs(point2.iX - point1.iX),Abs(point2.iY - point1.iY));
638 const TInt dotParam = iDotParam;
639 DoDrawLine(point2,point1,EFalse);
641 if (Abs(point2.iX - point1.iX) > Abs(point2.iY - point1.iY))
643 if (iPenStyle == CGraphicsContext::ESolidPen || (iDotMask & (1 << ((iDotParam / iPenSize.iWidth) % iDotLength))))
644 DoPlot((*aPointList)[count]);
648 if (iPenStyle == CGraphicsContext::ESolidPen || (iDotMask & (1 << ((iDotParam / iPenSize.iHeight) % iDotLength))))
649 DoPlot((*aPointList)[count]);
653 iDotParam = dotParam;
658 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
659 void CFbsBitGc::PolyFill(const TPoint* aPointList,TInt aNumPoints,TFillRule aFillRule)
666 const TInt limit = iDefaultRegionPtr->Count();
667 for (TInt count = 0; count < limit; count++)
669 iClipRect = (*iDefaultRegionPtr)[count];
671 if (UserClipRect(iClipRect))
674 CPolygonFiller polyfill;
675 polyfill.Construct(aPointList,aNumPoints,aFillRule);
677 for (polyfill.GetNextPixelRun(exists,scanline,pixelRunStart,pixelRunEnd);exists;
678 polyfill.GetNextPixelRun(exists,scanline,pixelRunStart,pixelRunEnd))
680 TPoint start(pixelRunStart,scanline),end(pixelRunEnd,scanline);
683 ClipFillLine(start,end);
687 iDevice->iDrawDevice->UpdateRegion(iClipRect);
691 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
692 void CFbsBitGc::PolyFillLarge(const TPoint* aPointList,TInt aNumPoints,TFillRule aFillRule)
698 const TInt limit = iDefaultRegionPtr->Count();
699 for (TInt count = 0; count < limit; count++)
701 iClipRect = (*iDefaultRegionPtr)[count];
703 if (UserClipRect(iClipRect))
706 CPolygonFiller polyfill;
707 polyfill.Construct(aPointList,aNumPoints,aFillRule,CPolygonFiller::EGetPixelRunsSequentiallyForSpecifiedScanLines);
708 TInt clipRectOffsetStart = iClipRect.iTl.iY - iOrigin.iY;
709 TInt clipRectOffsetEnd = iClipRect.iBr.iY - iOrigin.iY;
711 for (TInt scanline = clipRectOffsetStart; scanline < clipRectOffsetEnd; scanline++)
713 polyfill.GetNextPixelRunOnSpecifiedScanLine(exists,scanline,pixelRunStart,pixelRunEnd);
716 TPoint start(pixelRunStart,scanline),end(pixelRunEnd,scanline);
719 ClipFillLine(start,end);
721 polyfill.GetNextPixelRunOnSpecifiedScanLine(exists,scanline,pixelRunStart,pixelRunEnd);
726 iDevice->iDrawDevice->UpdateRegion(iClipRect);
730 void CFbsBitGc::PolyOutline(const TPoint* aPointList,TInt aNumPoints)
732 for (TInt count = 0; count < aNumPoints; count++)
734 TPoint point1(aPointList[count]);
735 TPoint point2(aPointList[(count + 1) % aNumPoints]);
737 if (point1.iY < point2.iY)
738 DoDrawLine(point1,point2,ETrue);
742 iDotParam += Max(Abs(point2.iX - point1.iX),Abs(point2.iY - point1.iY));
743 const TInt dotParam = iDotParam;
745 DoDrawLine(point2,point1,EFalse);
747 if (Abs(point2.iX - point1.iX) > Abs(point2.iY - point1.iY))
749 if (iPenStyle == CGraphicsContext::ESolidPen || (iDotMask & (1 << ((iDotParam / iPenSize.iWidth) % iDotLength))))
750 DoPlot(aPointList[count]);
754 if (iPenStyle == CGraphicsContext::ESolidPen || (iDotMask & (1 << ((iDotParam / iPenSize.iHeight) % iDotLength))))
755 DoPlot(aPointList[count]);
759 iDotParam = dotParam;