--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdirect.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,416 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "directgdiadapter.h"
+#include "swdirectgdiengine.h"
+
+/**
+@see MDirectGdiEngine::CopyRect()
+*/
+void CSwDirectGdiEngine::CopyRect(const TPoint& aOffset, const TRect& aRect)
+ {
+ TRect deviceRect;
+ iDrawDevice->GetDrawRect(deviceRect);
+ const TPoint back(TPoint(0,0) - aOffset);
+ TRect rcpy(aRect);
+ rcpy.Move(iOrigin);
+ rcpy.Intersection(deviceRect);
+ ((TRegion*)iDefaultRegionPtr)->Sort(aOffset);
+
+ TRect targetRect(rcpy);
+ targetRect.Move(aOffset);
+ targetRect.BoundingRect(rcpy);
+
+ TRect clipRect(0,0,0,0);
+ const TInt limit = iDefaultRegionPtr->Count();
+ for(TInt count = 0; count < limit; count++)
+ {
+ clipRect = (*iDefaultRegionPtr)[count];
+
+ clipRect.Move(back);
+ if (!clipRect.Intersects(rcpy))
+ {
+ continue;
+ }
+
+ clipRect.Intersection(rcpy);
+ DirectGdi::TDrawMode drawMode = iDrawMode;
+ iDrawMode = DirectGdi::EDrawModeWriteAlpha;
+ DoCopyRect(aOffset, clipRect);
+ iDrawMode = drawMode; // restore the previous draw mode
+ clipRect.Move(aOffset);
+ iDrawDevice->UpdateRegion(clipRect);
+ }
+ }
+
+/**
+@see CopyRect()
+@panic DGDIAdapter 1013, if aRect or aOffset are outside of the destination bounds (debug only).
+ */
+void CSwDirectGdiEngine::DoCopyRect(const TPoint& aOffset, const TRect& aRect)
+ {
+#ifdef _DEBUG
+ TRect deviceRect;
+ iDrawDevice->GetDrawRect(deviceRect);
+#endif
+ GRAPHICS_ASSERT_DEBUG(aRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(aRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(aRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(aRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
+
+ TRect offsetRect(aRect);
+ offsetRect.Move(aOffset);
+
+ GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
+
+ TInt y1 = aRect.iTl.iY;
+ TInt y2 = aRect.iBr.iY;
+ TInt yinc = 1; // default y2>y1
+ if (aOffset.iY > 0) // y1>y2
+ {
+ y1 = aRect.iBr.iY - 1;
+ y2 = aRect.iTl.iY - 1;
+ yinc = -1;
+ }
+
+ const TInt width = aRect.Width();
+ const TInt xoffset = aRect.iTl.iX + aOffset.iX;
+ const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
+ TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
+
+ for (TInt row = y1; row != y2; row += yinc)
+ {
+ iDrawDevice->ReadLine(aRect.iTl.iX, row, width, scanLineBuffer, dispMode);
+ iDrawDevice->WriteLine(xoffset, row + aOffset.iY, width, scanLineBuffer, GcDrawMode(iDrawMode));
+ }
+ }
+
+/**
+@see MDirectGdiEngine::DrawRect()
+*/
+void CSwDirectGdiEngine::DrawRect(const TRect& aRect)
+ {
+ TRect rcpy(aRect);
+
+ iBrushBitmap.BeginDataAccess();
+
+ if ((iPenSize.iWidth == 1) && (iPenSize.iHeight == 1) && iPenStyle != DirectGdi::ENullPen)
+ {
+ const TInt width = rcpy.Width();
+ const TInt height = rcpy.Height();
+ const TPoint currentLinePosition = iLinePosition;
+
+ if (iPenStyle != DirectGdi::ESolidPen)
+ {
+ iDotParam = 0;
+ }
+
+ DoDrawLine(rcpy.iTl,TPoint(rcpy.iBr.iX,rcpy.iTl.iY),ETrue); // top
+
+ if (height > 2 && width > 1)
+ {
+ DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iTl.iY+1),TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),ETrue); // right
+ }
+
+ if (height > 1)
+ {
+ DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),TPoint(rcpy.iTl.iX-1,rcpy.iBr.iY-1),ETrue); // bottom
+ }
+
+ if (height > 2)
+ {
+ DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left
+ }
+
+ // Restore internal line position in case it has been modified by DoDrawLine().
+ // DrawRect() should not be modifying it.
+ iLinePosition = currentLinePosition;
+
+ if (width < 3 || height < 3)
+ {
+ goto nofill;
+ }
+
+ rcpy.Shrink(1,1);
+ rcpy.Move(iOrigin);
+ }
+ else if ((iPenStyle != DirectGdi::ENullPen) && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1))
+ {
+ rcpy.Move(iOrigin);
+
+ const DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle;
+ const TRgb tempbrushColor = iBrushColor;
+ const DirectGdi::TDrawMode tempdrawmode = iDrawMode;
+
+ const TInt halfpenwidth = (iPenSize.iWidth - 1) >> 1;
+ const TInt halfpenheight = (iPenSize.iHeight - 1) >> 1;
+ const TInt otherhalfwidth = (iPenSize.iWidth >> 1) + 1;
+ const TInt otherhalfheight = (iPenSize.iHeight >> 1) + 1;
+
+ rcpy.iBr.iX--;
+ rcpy.iBr.iY--;
+
+ if (((rcpy.iBr.iY - rcpy.iTl.iY) <= (iPenSize.iHeight + 1)) || ((rcpy.iBr.iX - rcpy.iTl.iX) <= (iPenSize.iWidth + 1)))
+ {
+ iBrushColor = iPenColor;
+ iBrushStyle = DirectGdi::ESolidBrush;
+ if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
+ {
+ iDrawMode = DirectGdi::EDrawModePEN;
+ }
+
+ rcpy.iTl.iX -= halfpenwidth;
+ rcpy.iTl.iY -= halfpenheight;
+ rcpy.iBr.iX += otherhalfwidth;
+ rcpy.iBr.iY += otherhalfheight;
+ RectFill(rcpy);
+ }
+ else
+ {
+ // In the event the pen outline is semi-transparent, we must do the fill first so that the
+ // outline is blended over the top.
+ RectFill(rcpy);
+
+ iBrushColor = iPenColor;
+ iBrushStyle = DirectGdi::ESolidBrush;
+ if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
+ {
+ iDrawMode = DirectGdi::EDrawModePEN;
+ }
+ RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iTl.iY + otherhalfheight)); // top
+ RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iTl.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // left
+ RectFill(TRect(rcpy.iBr.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // right
+ RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iBr.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY + otherhalfheight)); // bottom
+ }
+
+ iBrushStyle = tempbrushstyle;
+ iBrushColor = tempbrushColor;
+ iDrawMode = tempdrawmode;
+ goto nofill;
+ }
+ else
+ {
+ rcpy.Move(iOrigin);
+ }
+
+ RectFill(rcpy);
+
+nofill:
+ iBrushBitmap.EndDataAccess(ETrue);
+ }
+
+/**
+Fills the given area using the current brush.
+
+@param aRect The area to fill.
+@panic DGDIAdapter 1013, if the a clipping rectangle is fully outside of the destination bounds (debug only).
+@panic DGDIAdapter 7, if using EPatternedBrush with no brush pattern bitmap.
+ */
+void CSwDirectGdiEngine::RectFill(const TRect& aRect)
+ {
+ if (aRect.IsEmpty() || iBrushStyle == DirectGdi::ENullBrush)
+ {
+ return;
+ }
+
+ const TPoint origin = iOrigin + iBrushOrigin;
+ const TInt limit = iDefaultRegionPtr->Count();
+ TRect clipRect(0,0,0,0);
+ for (TInt count = 0; count < limit; count++)
+ {
+ clipRect = (*iDefaultRegionPtr)[count];
+ if (!clipRect.Intersects(aRect))
+ {
+ continue;
+ }
+
+ clipRect.Intersection(aRect);
+
+#ifdef _DEBUG
+ TRect deviceRect;
+ iDrawDevice->GetDrawRect(deviceRect);
+ GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
+ GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
+#endif
+
+ TInt xcoord = clipRect.iTl.iX;
+ TInt ycoord = clipRect.iTl.iY;
+ const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
+
+ switch(iBrushStyle)
+ {
+ case DirectGdi::ESolidBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ break;
+ case DirectGdi::EPatternedBrush:
+ {
+ iBrushBitmap.BeginDataAccess();
+ CBitwiseBitmap* brushbitmap = iBrushBitmap.Address();
+
+ GRAPHICS_ASSERT_ALWAYS(brushbitmap != NULL, EDirectGdiPanicInvalidBitmap);
+
+ TRect sourcerect(clipRect);
+ sourcerect.Move(-origin);
+
+ DoBitBlt(clipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect);
+ iBrushBitmap.EndDataAccess(ETrue);
+ break;
+ }
+ case DirectGdi::EHorizontalHatchBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ while (Abs((ycoord - origin.iY) % 3) != 2)
+ {
+ ycoord++;
+ }
+ for (; ycoord < clipRect.iBr.iY; ycoord += 3)
+ {
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
+ }
+ break;
+ case DirectGdi::EVerticalHatchBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ while (Abs((xcoord - origin.iX) % 3) != 2)
+ {
+ xcoord++;
+ }
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgbMulti(xcoord,clipRect.iTl.iY,1,clipRect.Height(),iPenColor,drawMode);
+ }
+ break;
+ case DirectGdi::ESquareCrossHatchBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ while (Abs((ycoord - origin.iY) % 3) != 2)
+ {
+ ycoord++;
+ }
+ for (; ycoord < clipRect.iBr.iY; ycoord += 3) // horizontal lines
+ {
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
+ }
+
+ ycoord = clipRect.iTl.iY;
+ while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < clipRect.iBr.iY) // above the top horizontal line
+ {
+ xcoord = clipRect.iTl.iX;
+ while (Abs((xcoord - origin.iX) % 3) != 2)
+ {
+ xcoord++;
+ }
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
+ }
+ ycoord++;
+ }
+ ycoord += 3;
+ for (; ycoord < clipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals
+ {
+ xcoord = clipRect.iTl.iX;
+ while (Abs((xcoord - origin.iX) % 3) != 2)
+ {
+ xcoord++;
+ }
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,drawMode);
+ }
+ }
+
+ ycoord -= 3;
+ while (ycoord < clipRect.iBr.iY) // below the bottom horizontal
+ {
+ xcoord = clipRect.iTl.iX;
+ while (Abs((xcoord - origin.iX) % 3) != 2)
+ {
+ xcoord++;
+ }
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
+ }
+ ycoord++;
+ }
+ break;
+ case DirectGdi::EForwardDiagonalHatchBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ for (; ycoord < clipRect.iBr.iY; ycoord++)
+ {
+ xcoord = clipRect.iTl.iX;
+ TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3;
+ if (diff < 0)
+ {
+ diff += 3;
+ }
+ xcoord += diff;
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
+ }
+ }
+ break;
+ case DirectGdi::ERearwardDiagonalHatchBrush:
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ for (; ycoord < clipRect.iBr.iY; ycoord++)
+ {
+ xcoord = clipRect.iTl.iX;
+ TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3;
+ if (diff < 0)
+ {
+ diff += 3;
+ }
+ xcoord += diff;
+ for (; xcoord < clipRect.iBr.iX; xcoord += 3)
+ {
+ iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
+ }
+ }
+ break;
+ case DirectGdi::EDiamondCrossHatchBrush:
+ {
+ iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
+ clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
+ TInt sum = xcoord + ycoord - origin.iX - origin.iY;
+ for (; ycoord < clipRect.iBr.iY; ycoord++,sum++)
+ {
+ TInt currentsum = sum;
+ for (xcoord = clipRect.iTl.iX; xcoord < clipRect.iBr.iX; xcoord++,currentsum++)
+ {
+ if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1))
+ {
+ iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ return;
+ }
+
+ iDrawDevice->UpdateRegion(clipRect);
+ }
+ }