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: sl@0: /** sl@0: @see MDirectGdiEngine::CopyRect() sl@0: */ sl@0: void CSwDirectGdiEngine::CopyRect(const TPoint& aOffset, const TRect& aRect) sl@0: { sl@0: TRect deviceRect; sl@0: iDrawDevice->GetDrawRect(deviceRect); sl@0: const TPoint back(TPoint(0,0) - aOffset); sl@0: TRect rcpy(aRect); sl@0: rcpy.Move(iOrigin); sl@0: rcpy.Intersection(deviceRect); sl@0: ((TRegion*)iDefaultRegionPtr)->Sort(aOffset); sl@0: sl@0: TRect targetRect(rcpy); sl@0: targetRect.Move(aOffset); sl@0: targetRect.BoundingRect(rcpy); sl@0: sl@0: TRect clipRect(0,0,0,0); 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: sl@0: clipRect.Move(back); sl@0: if (!clipRect.Intersects(rcpy)) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: clipRect.Intersection(rcpy); sl@0: DirectGdi::TDrawMode drawMode = iDrawMode; sl@0: iDrawMode = DirectGdi::EDrawModeWriteAlpha; sl@0: DoCopyRect(aOffset, clipRect); sl@0: iDrawMode = drawMode; // restore the previous draw mode sl@0: clipRect.Move(aOffset); sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: @see CopyRect() sl@0: @panic DGDIAdapter 1013, if aRect or aOffset are outside of the destination bounds (debug only). sl@0: */ sl@0: void CSwDirectGdiEngine::DoCopyRect(const TPoint& aOffset, const TRect& aRect) sl@0: { sl@0: #ifdef _DEBUG sl@0: TRect deviceRect; sl@0: iDrawDevice->GetDrawRect(deviceRect); sl@0: #endif sl@0: GRAPHICS_ASSERT_DEBUG(aRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(aRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: sl@0: TRect offsetRect(aRect); sl@0: offsetRect.Move(aOffset); sl@0: sl@0: GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: sl@0: TInt y1 = aRect.iTl.iY; sl@0: TInt y2 = aRect.iBr.iY; sl@0: TInt yinc = 1; // default y2>y1 sl@0: if (aOffset.iY > 0) // y1>y2 sl@0: { sl@0: y1 = aRect.iBr.iY - 1; sl@0: y2 = aRect.iTl.iY - 1; sl@0: yinc = -1; sl@0: } sl@0: sl@0: const TInt width = aRect.Width(); sl@0: const TInt xoffset = aRect.iTl.iX + aOffset.iX; sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice); sl@0: TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer(); sl@0: sl@0: for (TInt row = y1; row != y2; row += yinc) sl@0: { sl@0: iDrawDevice->ReadLine(aRect.iTl.iX, row, width, scanLineBuffer, dispMode); sl@0: iDrawDevice->WriteLine(xoffset, row + aOffset.iY, width, scanLineBuffer, GcDrawMode(iDrawMode)); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: @see MDirectGdiEngine::DrawRect() sl@0: */ sl@0: void CSwDirectGdiEngine::DrawRect(const TRect& aRect) sl@0: { sl@0: TRect rcpy(aRect); sl@0: sl@0: iBrushBitmap.BeginDataAccess(); sl@0: sl@0: if ((iPenSize.iWidth == 1) && (iPenSize.iHeight == 1) && iPenStyle != DirectGdi::ENullPen) sl@0: { sl@0: const TInt width = rcpy.Width(); sl@0: const TInt height = rcpy.Height(); sl@0: const TPoint currentLinePosition = iLinePosition; sl@0: sl@0: if (iPenStyle != DirectGdi::ESolidPen) sl@0: { sl@0: iDotParam = 0; sl@0: } sl@0: sl@0: DoDrawLine(rcpy.iTl,TPoint(rcpy.iBr.iX,rcpy.iTl.iY),ETrue); // top sl@0: sl@0: if (height > 2 && width > 1) sl@0: { sl@0: DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iTl.iY+1),TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),ETrue); // right sl@0: } sl@0: sl@0: if (height > 1) sl@0: { sl@0: DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),TPoint(rcpy.iTl.iX-1,rcpy.iBr.iY-1),ETrue); // bottom sl@0: } sl@0: sl@0: if (height > 2) sl@0: { sl@0: DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left sl@0: } sl@0: sl@0: // Restore internal line position in case it has been modified by DoDrawLine(). sl@0: // DrawRect() should not be modifying it. sl@0: iLinePosition = currentLinePosition; sl@0: sl@0: if (width < 3 || height < 3) sl@0: { sl@0: goto nofill; sl@0: } sl@0: sl@0: rcpy.Shrink(1,1); sl@0: rcpy.Move(iOrigin); sl@0: } sl@0: else if ((iPenStyle != DirectGdi::ENullPen) && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1)) sl@0: { sl@0: rcpy.Move(iOrigin); sl@0: sl@0: const DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle; sl@0: const TRgb tempbrushColor = iBrushColor; sl@0: const DirectGdi::TDrawMode tempdrawmode = iDrawMode; sl@0: sl@0: const TInt halfpenwidth = (iPenSize.iWidth - 1) >> 1; sl@0: const TInt halfpenheight = (iPenSize.iHeight - 1) >> 1; sl@0: const TInt otherhalfwidth = (iPenSize.iWidth >> 1) + 1; sl@0: const TInt otherhalfheight = (iPenSize.iHeight >> 1) + 1; sl@0: sl@0: rcpy.iBr.iX--; sl@0: rcpy.iBr.iY--; sl@0: sl@0: if (((rcpy.iBr.iY - rcpy.iTl.iY) <= (iPenSize.iHeight + 1)) || ((rcpy.iBr.iX - rcpy.iTl.iX) <= (iPenSize.iWidth + 1))) sl@0: { sl@0: iBrushColor = iPenColor; sl@0: iBrushStyle = DirectGdi::ESolidBrush; sl@0: if(iDrawMode != DirectGdi::EDrawModeWriteAlpha) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModePEN; sl@0: } sl@0: sl@0: rcpy.iTl.iX -= halfpenwidth; sl@0: rcpy.iTl.iY -= halfpenheight; sl@0: rcpy.iBr.iX += otherhalfwidth; sl@0: rcpy.iBr.iY += otherhalfheight; sl@0: RectFill(rcpy); sl@0: } sl@0: else sl@0: { sl@0: // In the event the pen outline is semi-transparent, we must do the fill first so that the sl@0: // outline is blended over the top. sl@0: RectFill(rcpy); sl@0: sl@0: iBrushColor = iPenColor; sl@0: iBrushStyle = DirectGdi::ESolidBrush; sl@0: if(iDrawMode != DirectGdi::EDrawModeWriteAlpha) sl@0: { sl@0: iDrawMode = DirectGdi::EDrawModePEN; sl@0: } sl@0: RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iTl.iY + otherhalfheight)); // top sl@0: RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iTl.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // left sl@0: RectFill(TRect(rcpy.iBr.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // right sl@0: RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iBr.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY + otherhalfheight)); // bottom sl@0: } sl@0: sl@0: iBrushStyle = tempbrushstyle; sl@0: iBrushColor = tempbrushColor; sl@0: iDrawMode = tempdrawmode; sl@0: goto nofill; sl@0: } sl@0: else sl@0: { sl@0: rcpy.Move(iOrigin); sl@0: } sl@0: sl@0: RectFill(rcpy); sl@0: sl@0: nofill: sl@0: iBrushBitmap.EndDataAccess(ETrue); sl@0: } sl@0: sl@0: /** sl@0: Fills the given area using the current brush. sl@0: sl@0: @param aRect The area to fill. sl@0: @panic DGDIAdapter 1013, if the a clipping rectangle is fully outside of the destination bounds (debug only). sl@0: @panic DGDIAdapter 7, if using EPatternedBrush with no brush pattern bitmap. sl@0: */ sl@0: void CSwDirectGdiEngine::RectFill(const TRect& aRect) sl@0: { sl@0: if (aRect.IsEmpty() || iBrushStyle == DirectGdi::ENullBrush) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: const TPoint origin = iOrigin + iBrushOrigin; sl@0: const TInt limit = iDefaultRegionPtr->Count(); sl@0: TRect clipRect(0,0,0,0); sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: clipRect = (*iDefaultRegionPtr)[count]; sl@0: if (!clipRect.Intersects(aRect)) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: clipRect.Intersection(aRect); sl@0: sl@0: #ifdef _DEBUG sl@0: TRect deviceRect; sl@0: iDrawDevice->GetDrawRect(deviceRect); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds); sl@0: GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds); sl@0: #endif sl@0: sl@0: TInt xcoord = clipRect.iTl.iX; sl@0: TInt ycoord = clipRect.iTl.iY; 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(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: break; sl@0: case DirectGdi::EPatternedBrush: sl@0: { sl@0: iBrushBitmap.BeginDataAccess(); sl@0: CBitwiseBitmap* brushbitmap = iBrushBitmap.Address(); sl@0: sl@0: GRAPHICS_ASSERT_ALWAYS(brushbitmap != NULL, EDirectGdiPanicInvalidBitmap); sl@0: sl@0: TRect sourcerect(clipRect); sl@0: sourcerect.Move(-origin); sl@0: sl@0: DoBitBlt(clipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect); sl@0: iBrushBitmap.EndDataAccess(ETrue); sl@0: break; sl@0: } sl@0: case DirectGdi::EHorizontalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: while (Abs((ycoord - origin.iY) % 3) != 2) sl@0: { sl@0: ycoord++; sl@0: } sl@0: for (; ycoord < clipRect.iBr.iY; ycoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode); sl@0: } sl@0: break; sl@0: case DirectGdi::EVerticalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: { sl@0: xcoord++; sl@0: } sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(xcoord,clipRect.iTl.iY,1,clipRect.Height(),iPenColor,drawMode); sl@0: } sl@0: break; sl@0: case DirectGdi::ESquareCrossHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: while (Abs((ycoord - origin.iY) % 3) != 2) sl@0: { sl@0: ycoord++; sl@0: } sl@0: for (; ycoord < clipRect.iBr.iY; ycoord += 3) // horizontal lines sl@0: { sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode); sl@0: } sl@0: sl@0: ycoord = clipRect.iTl.iY; sl@0: while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < clipRect.iBr.iY) // above the top horizontal line sl@0: { sl@0: xcoord = clipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: { sl@0: xcoord++; sl@0: } sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode); sl@0: } sl@0: ycoord++; sl@0: } sl@0: ycoord += 3; sl@0: for (; ycoord < clipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals sl@0: { sl@0: xcoord = clipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: { sl@0: xcoord++; sl@0: } sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,drawMode); sl@0: } sl@0: } sl@0: sl@0: ycoord -= 3; sl@0: while (ycoord < clipRect.iBr.iY) // below the bottom horizontal sl@0: { sl@0: xcoord = clipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: { sl@0: xcoord++; sl@0: } sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode); sl@0: } sl@0: ycoord++; sl@0: } sl@0: break; sl@0: case DirectGdi::EForwardDiagonalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: for (; ycoord < clipRect.iBr.iY; ycoord++) sl@0: { sl@0: xcoord = clipRect.iTl.iX; sl@0: TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3; sl@0: if (diff < 0) sl@0: { sl@0: diff += 3; sl@0: } sl@0: xcoord += diff; sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode); sl@0: } sl@0: } sl@0: break; sl@0: case DirectGdi::ERearwardDiagonalHatchBrush: sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: for (; ycoord < clipRect.iBr.iY; ycoord++) sl@0: { sl@0: xcoord = clipRect.iTl.iX; sl@0: TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3; sl@0: if (diff < 0) sl@0: { sl@0: diff += 3; sl@0: } sl@0: xcoord += diff; sl@0: for (; xcoord < clipRect.iBr.iX; xcoord += 3) sl@0: { sl@0: iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode); sl@0: } sl@0: } sl@0: break; sl@0: case DirectGdi::EDiamondCrossHatchBrush: sl@0: { sl@0: iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY, sl@0: clipRect.Width(),clipRect.Height(),iBrushColor,drawMode); sl@0: TInt sum = xcoord + ycoord - origin.iX - origin.iY; sl@0: for (; ycoord < clipRect.iBr.iY; ycoord++,sum++) sl@0: { sl@0: TInt currentsum = sum; sl@0: for (xcoord = clipRect.iTl.iX; xcoord < clipRect.iBr.iX; xcoord++,currentsum++) sl@0: { sl@0: if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1)) sl@0: { sl@0: iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode); sl@0: } sl@0: } sl@0: } sl@0: break; sl@0: } sl@0: default: sl@0: return; sl@0: } sl@0: sl@0: iDrawDevice->UpdateRegion(clipRect); sl@0: } sl@0: }