sl@0: // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "directgdiadapter.h" sl@0: #include "swdirectgdiengine.h" sl@0: #include "swdirectgdiellipse.h" sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::Clear(const TRect&) sl@0: */ sl@0: void CSwDirectGdiEngine::Clear(const TRect& aRect) sl@0: { sl@0: TRect rcpy(aRect); sl@0: rcpy.Move(iOrigin); sl@0: sl@0: DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle; sl@0: iBrushStyle = DirectGdi::ESolidBrush; sl@0: sl@0: RectFill(rcpy); sl@0: sl@0: iBrushStyle = tempbrushstyle; sl@0: } sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::Clear() sl@0: */ sl@0: void CSwDirectGdiEngine::Clear() sl@0: { sl@0: TRect deviceRect; sl@0: iDrawDevice->GetDrawRect(deviceRect); sl@0: if ((iOrigin.iX!=0) || (iOrigin.iY!=0)) sl@0: { sl@0: deviceRect.Move(-iOrigin); sl@0: } sl@0: Clear(deviceRect); sl@0: } sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::Plot() sl@0: */ sl@0: void CSwDirectGdiEngine::Plot(const TPoint& aPoint) sl@0: { sl@0: TRect targetRect(aPoint + iOrigin, TSize(1,1)); sl@0: targetRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1); sl@0: DoPlot(aPoint); sl@0: } sl@0: sl@0: /** sl@0: Draws a single point. sl@0: sl@0: @see Plot() sl@0: sl@0: @param aPoint The location to plot at. sl@0: @panic DGDIAdapter 1013, if the point being plotted is out of bounds of the target (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::DoPlot(const TPoint& aPoint) sl@0: { sl@0: const TSize oneByOne(1,1); sl@0: const TPoint point(aPoint + iOrigin); sl@0: sl@0: TRect temp(point,oneByOne); sl@0: if (iPenSize.iWidth > 1 || iPenSize.iHeight > 1) sl@0: { sl@0: temp.Grow(iPenSize.iWidth >> 1, iPenSize.iHeight >> 1); sl@0: } sl@0: sl@0: const DirectGdi::TPenStyle oldPenStyle = iPenStyle; sl@0: iPenStyle = DirectGdi::ESolidPen; sl@0: sl@0: #if defined(_DEBUG) sl@0: TRect deviceRect; sl@0: iDrawDevice->GetDrawRect(deviceRect); sl@0: #endif sl@0: sl@0: TRect clipRect; sl@0: const TInt limit = iDefaultRegionPtr->Count(); sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: clipRect = (*iDefaultRegionPtr)[count]; sl@0: if (!clipRect.Intersects(temp)) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: clipRect.Intersection(temp); sl@0: if (iPenSize == oneByOne) sl@0: { sl@0: if (clipRect.Contains(point)) sl@0: { sl@0: GRAPHICS_ASSERT_DEBUG(point.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(point.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(point.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(point.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: sl@0: iDrawDevice->WriteRgb(point.iX,point.iY,iPenColor, GcDrawMode(iDrawMode)); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: PenDrawClipped(point, clipRect); sl@0: } sl@0: sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: sl@0: iPenStyle = oldPenStyle; sl@0: } sl@0: sl@0: /** sl@0: Clips the horizontal drawing of a line between two points. sl@0: The vertical location must be inside the clip rect. sl@0: sl@0: @param aLeft The left hand side coordinate. sl@0: @param aRight The right hand side coordinate. sl@0: @param aClipRect The rectangle to which the line is clipped. sl@0: */ sl@0: void CSwDirectGdiEngine::ClipFillLine(TPoint aLeft,TPoint aRight, TRect aClipRect) sl@0: { sl@0: if (aLeft.iY < aClipRect.iTl.iY || aLeft.iY >= aClipRect.iBr.iY) sl@0: return; sl@0: sl@0: aLeft.iX = Max(aLeft.iX,aClipRect.iTl.iX); sl@0: aRight.iX = Min(aRight.iX,aClipRect.iBr.iX-1); sl@0: if (aLeft.iX > aRight.iX) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: TInt xcoord = aLeft.iX; sl@0: TInt length = aRight.iX - aLeft.iX + 1; sl@0: TPoint origin(iOrigin + iBrushOrigin); sl@0: const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode); sl@0: sl@0: switch(iBrushStyle) sl@0: { sl@0: case DirectGdi::ESolidBrush: sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: return; sl@0: case DirectGdi::EPatternedBrush: sl@0: { sl@0: iBrushBitmap.BeginDataAccess(); sl@0: CBitwiseBitmap* brushBitmap = iBrushBitmap.Address(); sl@0: if (brushBitmap) sl@0: { sl@0: TRect sourcerect(aLeft,TSize(length,1)); sl@0: sourcerect.Move(-origin); sl@0: DoBitBlt(aLeft,brushBitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect); sl@0: } sl@0: iBrushBitmap.EndDataAccess(ETrue); sl@0: return; sl@0: } sl@0: case DirectGdi::EHorizontalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: if (Abs((aLeft.iY - origin.iY) % 3) == 2) sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode); sl@0: return; sl@0: case DirectGdi::EVerticalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < aLeft.iX + length; xcoord += 3) sl@0: iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); sl@0: return; sl@0: case DirectGdi::ESquareCrossHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: if (Abs((aLeft.iY - origin.iY) % 3) == 2) sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iPenColor,drawMode); sl@0: else sl@0: { sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < aLeft.iX + length; xcoord += 3) sl@0: iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); sl@0: } sl@0: return; sl@0: case DirectGdi::EForwardDiagonalHatchBrush: sl@0: { sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: TInt diff = (origin.iX + origin.iY - aLeft.iX - aLeft.iY) % 3; sl@0: if (diff < 0) sl@0: diff += 3; sl@0: xcoord += diff; sl@0: for (; xcoord < aLeft.iX + length; xcoord += 3) sl@0: iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); sl@0: } sl@0: return; sl@0: case DirectGdi::ERearwardDiagonalHatchBrush: sl@0: { sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: TInt diff = (origin.iX - origin.iY - aLeft.iX + aLeft.iY) % 3; sl@0: if (diff < 0) sl@0: diff += 3; sl@0: xcoord += diff; sl@0: for (; xcoord < aLeft.iX + length; xcoord += 3) sl@0: iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); sl@0: } sl@0: return; sl@0: case DirectGdi::EDiamondCrossHatchBrush: sl@0: { sl@0: iDrawDevice->WriteRgbMulti(aLeft.iX,aLeft.iY,length,1,iBrushColor,drawMode); sl@0: TInt sum = aLeft.iX + aLeft.iY - origin.iX - origin.iY; sl@0: for (; xcoord < aLeft.iX + length; xcoord++,sum++) sl@0: if ((sum & 1) == 0 && ((sum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1)) sl@0: iDrawDevice->WriteRgb(xcoord,aLeft.iY,iPenColor,drawMode); sl@0: } sl@0: return; sl@0: default: sl@0: return; sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Creates the pen using the current pen size. sl@0: sl@0: @return KErrNoMermory if memory could not be allocated, KErrNone otherwise. sl@0: */ sl@0: TInt CSwDirectGdiEngine::PenAllocate() sl@0: { sl@0: ResetPenArray(); sl@0: sl@0: if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: const TInt doublePenHeight = iPenSize.iHeight << 1; sl@0: sl@0: TInt* penArray = new TInt[doublePenHeight]; sl@0: if (penArray == NULL) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: sl@0: SetPenArray(penArray); sl@0: sl@0: if (iPenSize.iWidth == 1 || iPenSize.iWidth == 2 || iPenSize.iHeight == 1 || iPenSize.iHeight == 2) sl@0: { sl@0: for (TInt count = 0; count < iPenSize.iHeight; count += 2) sl@0: { sl@0: iPenArray[doublePenHeight - count - 2] = 0; sl@0: iPenArray[doublePenHeight - count - 1] = iPenSize.iWidth - 1; sl@0: iPenArray[count] = 0; sl@0: iPenArray[count + 1] = iPenSize.iWidth - 1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TPoint tl,tr,bl,br; sl@0: TSwDirectGdiEllipse ellipse; sl@0: ellipse.Construct(TRect(iPenSize)); sl@0: for (TInt count = 0; count < iPenSize.iHeight; count += 2) sl@0: { sl@0: //coverity[check_return] sl@0: //coverity[unchecked_value] sl@0: ellipse.NextStep(tl,tr,bl,br); sl@0: iPenArray[doublePenHeight - count - 2] = bl.iX; sl@0: iPenArray[doublePenHeight - count - 1] = br.iX; sl@0: iPenArray[count] = tl.iX; sl@0: iPenArray[count + 1] = tr.iX; sl@0: } sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Draws at a given point using the current settings, if within clipping rectangle. sl@0: sl@0: @pre The pen size is greater than one. sl@0: sl@0: @param aPoint The location to draw at. sl@0: @param aClipRect The clipping rectangle. sl@0: @panic DGDIAdapter 1016, if the current pen size is zero (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::PenDrawClipped(TPoint aPoint, const TRect& aClipRect) sl@0: { sl@0: GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength); sl@0: GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength); sl@0: sl@0: aPoint.iX -= ((iPenSize.iWidth - 1) >> 1); sl@0: aPoint.iY -= ((iPenSize.iHeight - 1) >> 1); sl@0: sl@0: if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1) sl@0: { sl@0: if ( (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << (iDotParam % iDotLength)))) && sl@0: aClipRect.Contains(aPoint) ) sl@0: { sl@0: iDrawDevice->WriteRgb(aPoint.iX, aPoint.iY, iPenColor, GcDrawMode(iDrawMode)); sl@0: } sl@0: } sl@0: else if (iPenArray != NULL) sl@0: { sl@0: TInt yCoord = aPoint.iY; sl@0: const TInt maxdim = Max(iPenSize.iWidth,iPenSize.iHeight); sl@0: const TInt doublePenHeight = iPenSize.iHeight << 1; sl@0: sl@0: if (iPenStyle == DirectGdi::ESolidPen || (iDotMask & (1 << ((iDotParam / maxdim) % iDotLength)))) sl@0: { sl@0: for (TInt ix = 0; ix < doublePenHeight; yCoord++, ix += 2) sl@0: { sl@0: if (yCoord >= aClipRect.iTl.iY && yCoord < aClipRect.iBr.iY) sl@0: { sl@0: TInt left = aPoint.iX + iPenArray[ix]; sl@0: TInt right = aPoint.iX + iPenArray[ix+1]; sl@0: if (left < aClipRect.iTl.iX) sl@0: { sl@0: left = aClipRect.iTl.iX; sl@0: } sl@0: if (right >= aClipRect.iBr.iX) sl@0: { sl@0: right = aClipRect.iBr.iX - 1; sl@0: } sl@0: if (left <= right) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(left, yCoord, right - left + 1, 1, iPenColor, CGraphicsContext::EDrawModePEN); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: TPoint tl,tr,bl,br; sl@0: TSwDirectGdiEllipse ellipse; sl@0: ellipse.Construct(TRect(aPoint,iPenSize)); sl@0: while (!ellipse.NextStep(tl,tr,bl,br)) sl@0: { sl@0: if (tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY) sl@0: { sl@0: if (tl.iX < aClipRect.iTl.iX) sl@0: { sl@0: tl.iX = aClipRect.iTl.iX; sl@0: } sl@0: if (tr.iX >= aClipRect.iBr.iX) sl@0: { sl@0: tr.iX = aClipRect.iBr.iX-1; sl@0: } sl@0: if (tl.iX <= tr.iX) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN); sl@0: } sl@0: } sl@0: if (bl.iY >= aClipRect.iTl.iY && bl.iY < aClipRect.iBr.iY) sl@0: { sl@0: if (bl.iX < aClipRect.iTl.iX) sl@0: { sl@0: bl.iX = aClipRect.iTl.iX; sl@0: } sl@0: if (br.iX >= aClipRect.iBr.iX) sl@0: { sl@0: br.iX = aClipRect.iBr.iX - 1; sl@0: } sl@0: if (bl.iX <= br.iX) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(bl.iX,bl.iY,br.iX - bl.iX + 1,1,iPenColor,CGraphicsContext::EDrawModePEN); sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (tl.iY == bl.iY && tl.iY >= aClipRect.iTl.iY && tl.iY < aClipRect.iBr.iY) sl@0: { sl@0: if (tl.iX < aClipRect.iTl.iX) sl@0: { sl@0: tl.iX = aClipRect.iTl.iX; sl@0: } sl@0: if (tr.iX >= aClipRect.iBr.iX) sl@0: { sl@0: tr.iX = aClipRect.iBr.iX - 1; sl@0: } sl@0: if (tl.iX <= tr.iX) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(tl.iX,tl.iY,tr.iX - tl.iX + 1,1, iPenColor, CGraphicsContext::EDrawModePEN); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: @panic DGDIAdapter 1016, if the current pen size is zero (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::PenDrawDeferred(TPoint aPoint,TInt* aArray, TInt aFirstElement) sl@0: { sl@0: GRAPHICS_ASSERT_DEBUG(iPenArray,EDirectGdiPanicZeroLength); sl@0: GRAPHICS_ASSERT_DEBUG(iPenSize.iWidth > 0,EDirectGdiPanicZeroLength); sl@0: GRAPHICS_ASSERT_DEBUG(iPenSize.iHeight > 0,EDirectGdiPanicZeroLength); sl@0: sl@0: aPoint.iX -= ((iPenSize.iWidth - 1) >> 1); sl@0: const TInt doublepenheight = iPenSize.iHeight << 1; sl@0: sl@0: for (TInt ix = 0; ix < doublepenheight; ix++,aFirstElement++) sl@0: { sl@0: if (aFirstElement == doublepenheight) sl@0: { sl@0: aFirstElement = 0; sl@0: } sl@0: TInt newval = aPoint.iX + iPenArray[ix]; sl@0: if (newval < aArray[aFirstElement]) sl@0: { sl@0: aArray[aFirstElement] = newval; sl@0: } sl@0: sl@0: ix++; sl@0: aFirstElement++; sl@0: newval = aPoint.iX + iPenArray[ix]; sl@0: if (newval > aArray[aFirstElement]) sl@0: { sl@0: aArray[aFirstElement] = newval; sl@0: } sl@0: } sl@0: }