diff -r 000000000000 -r 5d03bc08d59c graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdigraphics.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdigraphics.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,422 @@ +// 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" +#include "swdirectgdiellipse.h" + +/** +@see MDirectGdiEngine::Clear(const TRect&) +*/ +void CSwDirectGdiEngine::Clear(const TRect& aRect) + { + TRect rcpy(aRect); + rcpy.Move(iOrigin); + + DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle; + iBrushStyle = DirectGdi::ESolidBrush; + + RectFill(rcpy); + + iBrushStyle = tempbrushstyle; + } + +/** +@see MDirectGdiEngine::Clear() +*/ +void CSwDirectGdiEngine::Clear() + { + TRect deviceRect; + iDrawDevice->GetDrawRect(deviceRect); + if ((iOrigin.iX!=0) || (iOrigin.iY!=0)) + { + deviceRect.Move(-iOrigin); + } + Clear(deviceRect); + } + +/** +@see MDirectGdiEngine::Plot() +*/ +void CSwDirectGdiEngine::Plot(const TPoint& aPoint) + { + TRect targetRect(aPoint + iOrigin, TSize(1,1)); + targetRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1); + DoPlot(aPoint); + } + +/** +Draws a single point. + +@see Plot() + +@param aPoint The location to plot at. +@panic DGDIAdapter 1013, if the point being plotted is out of bounds of the target (debug only). + */ +void CSwDirectGdiEngine::DoPlot(const TPoint& aPoint) + { + const TSize oneByOne(1,1); + const TPoint point(aPoint + iOrigin); + + TRect temp(point,oneByOne); + if (iPenSize.iWidth > 1 || iPenSize.iHeight > 1) + { + temp.Grow(iPenSize.iWidth >> 1, iPenSize.iHeight >> 1); + } + + const DirectGdi::TPenStyle oldPenStyle = iPenStyle; + iPenStyle = DirectGdi::ESolidPen; + +#if defined(_DEBUG) + TRect deviceRect; + iDrawDevice->GetDrawRect(deviceRect); +#endif + + TRect clipRect; + const TInt limit = iDefaultRegionPtr->Count(); + for (TInt count = 0; count < limit; count++) + { + clipRect = (*iDefaultRegionPtr)[count]; + if (!clipRect.Intersects(temp)) + { + continue; + } + + clipRect.Intersection(temp); + if (iPenSize == oneByOne) + { + if (clipRect.Contains(point)) + { + GRAPHICS_ASSERT_DEBUG(point.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds); + GRAPHICS_ASSERT_DEBUG(point.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds); + GRAPHICS_ASSERT_DEBUG(point.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds); + GRAPHICS_ASSERT_DEBUG(point.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds); + + iDrawDevice->WriteRgb(point.iX,point.iY,iPenColor, GcDrawMode(iDrawMode)); + } + } + else + { + PenDrawClipped(point, clipRect); + } + + iDrawDevice->UpdateRegion(clipRect); + } + + iPenStyle = oldPenStyle; + } + +/** +Clips the horizontal drawing of a line between two points. +The vertical location must be inside the clip rect. + +@param aLeft The left hand side coordinate. +@param aRight The right hand side coordinate. +@param aClipRect The rectangle to which the line is clipped. + */ +void CSwDirectGdiEngine::ClipFillLine(TPoint aLeft,TPoint aRight, TRect aClipRect) + { + if (aLeft.iY < aClipRect.iTl.iY || aLeft.iY >= aClipRect.iBr.iY) + return; + + aLeft.iX = Max(aLeft.iX,aClipRect.iTl.iX); + aRight.iX = Min(aRight.iX,aClipRect.iBr.iX-1); + if (aLeft.iX > aRight.iX) + { + return; + } + + TInt xcoord = aLeft.iX; + TInt length = aRight.iX - aLeft.iX + 1; + TPoint origin(iOrigin + iBrushOrigin); + const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode); + + switch(iBrushStyle) + { + case DirectGdi::ESolidBrush: + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + return; + case DirectGdi::EPatternedBrush: + { + iBrushBitmap.BeginDataAccess(); + CBitwiseBitmap* brushBitmap = iBrushBitmap.Address(); + if (brushBitmap) + { + TRect sourcerect(aLeft,TSize(length,1)); + sourcerect.Move(-origin); + DoBitBlt(aLeft,brushBitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect); + } + iBrushBitmap.EndDataAccess(ETrue); + return; + } + case DirectGdi::EHorizontalHatchBrush: + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + if (Abs((aLeft.iY - origin.iY) % 3) == 2) + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode); + return; + case DirectGdi::EVerticalHatchBrush: + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + while (Abs((xcoord - origin.iX) % 3) != 2) + xcoord++; + for (; xcoord < aLeft.iX + length; xcoord += 3) + iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); + return; + case DirectGdi::ESquareCrossHatchBrush: + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + if (Abs((aLeft.iY - origin.iY) % 3) == 2) + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode); + else + { + while (Abs((xcoord - origin.iX) % 3) != 2) + xcoord++; + for (; xcoord < aLeft.iX + length; xcoord += 3) + iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); + } + return; + case DirectGdi::EForwardDiagonalHatchBrush: + { + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + TInt diff = (origin.iX + origin.iY - aLeft.iX - aLeft.iY) % 3; + if (diff < 0) + diff += 3; + xcoord += diff; + for (; xcoord < aLeft.iX + length; xcoord += 3) + iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); + } + return; + case DirectGdi::ERearwardDiagonalHatchBrush: + { + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + TInt diff = (origin.iX - origin.iY - aLeft.iX + aLeft.iY) % 3; + if (diff < 0) + diff += 3; + xcoord += diff; + for (; xcoord < aLeft.iX + length; xcoord += 3) + iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); + } + return; + case DirectGdi::EDiamondCrossHatchBrush: + { + iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); + TInt sum = aLeft.iX + aLeft.iY - origin.iX - origin.iY; + for (; xcoord < aLeft.iX + length; xcoord++,sum++) + if ((sum & 1) == 0 && ((sum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1)) + iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); + } + return; + default: + return; + } + } + +/** +Creates the pen using the current pen size. + +@return KErrNoMermory if memory could not be allocated, KErrNone otherwise. +*/ +TInt CSwDirectGdiEngine::PenAllocate() + { + ResetPenArray(); + + if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1) + { + return KErrNone; + } + + const TInt doublePenHeight = iPenSize.iHeight << 1; + + TInt* penArray = new TInt[doublePenHeight]; + if (penArray == NULL) + { + return KErrNoMemory; + } + + SetPenArray(penArray); + + if (iPenSize.iWidth == 1 || iPenSize.iWidth == 2 || iPenSize.iHeight == 1 || iPenSize.iHeight == 2) + { + for (TInt count = 0; count < iPenSize.iHeight; count += 2) + { + iPenArray[doublePenHeight - count - 2] = 0; + iPenArray[doublePenHeight - count - 1] = iPenSize.iWidth - 1; + iPenArray[count] = 0; + iPenArray[count + 1] = iPenSize.iWidth - 1; + } + } + else + { + TPoint tl,tr,bl,br; + TSwDirectGdiEllipse ellipse; + ellipse.Construct(TRect(iPenSize)); + for (TInt count = 0; count < iPenSize.iHeight; count += 2) + { + //coverity[check_return] + //coverity[unchecked_value] + ellipse.NextStep(tl,tr,bl,br); + iPenArray[doublePenHeight - count - 2] = bl.iX; + iPenArray[doublePenHeight - count - 1] = br.iX; + iPenArray[count] = tl.iX; + iPenArray[count + 1] = tr.iX; + } + } + + return KErrNone; + } + +/** +Draws at a given point using the current settings, if within clipping rectangle. + +@pre The pen size is greater than one. + +@param aPoint The location to draw at. +@param aClipRect The clipping rectangle. +@panic DGDIAdapter 1016, if the current pen size is zero (debug only). +*/ +void CSwDirectGdiEngine::PenDrawClipped(TPoint aPoint, const TRect& aClipRect) + { + GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength); + GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength); + + aPoint.iX -= ((iPenSize.iWidth - 1) >> 1); + aPoint.iY -= ((iPenSize.iHeight - 1) >> 1); + + if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1) + { + if ( (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << (iDotParam % iDotLength)))) && + aClipRect.Contains(aPoint) ) + { + iDrawDevice->WriteRgb(aPoint.iX, aPoint.iY, iPenColor, GcDrawMode(iDrawMode)); + } + } + else if (iPenArray != NULL) + { + TInt yCoord = aPoint.iY; + const TInt maxdim = Max(iPenSize.iWidth,iPenSize.iHeight); + const TInt doublePenHeight = iPenSize.iHeight << 1; + + if (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << ((iDotParam / maxdim) % iDotLength)))) + { + for (TInt ix = 0; ix < doublePenHeight; yCoord++, ix += 2) + { + if (yCoord >= aClipRect.iTl.iY && yCoord < aClipRect.iBr.iY) + { + TInt left = aPoint.iX + iPenArray[ix]; + TInt right = aPoint.iX + iPenArray[ix+1]; + if (left < aClipRect.iTl.iX) + { + left = aClipRect.iTl.iX; + } + if (right >= aClipRect.iBr.iX) + { + right = aClipRect.iBr.iX - 1; + } + if (left <= right) + { + iDrawDevice->WriteRgbMulti(left, yCoord, right - left + 1, 1, iPenColor, CGraphicsContext::EDrawModePEN); + } + } + } + } + } + else + { + TPoint tl,tr,bl,br; + TSwDirectGdiEllipse ellipse; + ellipse.Construct(TRect(aPoint,iPenSize)); + while (!ellipse.NextStep(tl,tr,bl,br)) + { + if (tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY) + { + if (tl.iX < aClipRect.iTl.iX) + { + tl.iX = aClipRect.iTl.iX; + } + if (tr.iX >= aClipRect.iBr.iX) + { + tr.iX = aClipRect.iBr.iX-1; + } + if (tl.iX <= tr.iX) + { + iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN); + } + } + if (bl.iY >= aClipRect.iTl.iY && bl.iY < aClipRect.iBr.iY) + { + if (bl.iX < aClipRect.iTl.iX) + { + bl.iX = aClipRect.iTl.iX; + } + if (br.iX >= aClipRect.iBr.iX) + { + br.iX = aClipRect.iBr.iX - 1; + } + if (bl.iX <= br.iX) + { + iDrawDevice->WriteRgbMulti(bl.iX,bl.iY,br.iX - bl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN); + } + } + } + + if (tl.iY == bl.iY && tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY) + { + if (tl.iX < aClipRect.iTl.iX) + { + tl.iX = aClipRect.iTl.iX; + } + if (tr.iX >= aClipRect.iBr.iX) + { + tr.iX = aClipRect.iBr.iX - 1; + } + if (tl.iX <= tr.iX) + { + iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1, iPenColor, CGraphicsContext::EDrawModePEN); + } + } + } + } + +/** +@panic DGDIAdapter 1016, if the current pen size is zero (debug only). +*/ +void CSwDirectGdiEngine::PenDrawDeferred(TPoint aPoint,TInt* aArray, TInt aFirstElement) + { + GRAPHICS_ASSERT_DEBUG(iPenArray,EDirectGdiPanicZeroLength); + GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength); + GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength); + + aPoint.iX -= ((iPenSize.iWidth - 1) >> 1); + const TInt doublepenheight = iPenSize.iHeight << 1; + + for (TInt ix = 0; ix < doublepenheight; ix++,aFirstElement++) + { + if (aFirstElement == doublepenheight) + { + aFirstElement = 0; + } + TInt newval = aPoint.iX + iPenArray[ix]; + if (newval < aArray[aFirstElement]) + { + aArray[aFirstElement] = newval; + } + + ix++; + aFirstElement++; + newval = aPoint.iX + iPenArray[ix]; + if (newval > aArray[aFirstElement]) + { + aArray[aFirstElement] = newval; + } + } + }