sl@0: // Copyright (c) 1997-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 sl@0: #include sl@0: #include sl@0: #include sl@0: #include "BITPANIC.H" sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: /** sl@0: Copies a rectangle. sl@0: sl@0: The function provides a concrete implementation of the pure virtual sl@0: function CBitmapContext::CopyRect(). The function sl@0: behaviour is the same as documented in that class. sl@0: */ sl@0: EXPORT_C void CFbsBitGc::CopyRect(const TPoint& aOffset,const TRect& aRect) sl@0: { sl@0: if(CheckDevice(aRect) || aRect.IsEmpty() || aOffset == TPoint(0,0)) sl@0: return; sl@0: sl@0: CFbsDrawDevice* drawDevice = iDevice->iDrawDevice; sl@0: sl@0: TRect deviceRect; sl@0: drawDevice->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 clippedBoundingRect(rcpy); sl@0: clippedBoundingRect.Move(aOffset); sl@0: AddRect(clippedBoundingRect); sl@0: clippedBoundingRect.BoundingRect(rcpy); sl@0: if(!clippedBoundingRect.Intersects(iUserClipRect)) sl@0: return; sl@0: sl@0: SetupDevice(); sl@0: iDevice->DrawingBegin(); sl@0: sl@0: const TInt limit=iDefaultRegionPtr->Count(); sl@0: for(TInt count=0;countUpdateRegion(iClipRect); sl@0: } sl@0: sl@0: iDevice->DrawingEnd(); sl@0: } sl@0: sl@0: void CFbsBitGc::DoCopyRect(const TPoint& aOffset,const TRect& rect) sl@0: { sl@0: CFbsDrawDevice* drawDevice = iDevice->iDrawDevice; sl@0: #ifdef _DEBUG sl@0: TRect deviceRect; sl@0: drawDevice->GetDrawRect(deviceRect); sl@0: #endif sl@0: BG_ASSERT_DEBUG(rect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(rect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(rect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(rect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds); sl@0: sl@0: TRect offrect(rect); sl@0: offrect.Move(aOffset); sl@0: sl@0: BG_ASSERT_DEBUG(offrect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(offrect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(offrect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(offrect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds); sl@0: sl@0: TInt y1 = rect.iTl.iY,y2 = rect.iBr.iY,yinc = 1; // default y2>y1 sl@0: if (aOffset.iY > 0) // y1>y2 sl@0: { sl@0: y1 = rect.iBr.iY - 1; sl@0: y2 = rect.iTl.iY - 1; sl@0: yinc = -1; sl@0: } sl@0: sl@0: const TInt width = rect.Width(); sl@0: const TInt xoffset = rect.iTl.iX + aOffset.iX; sl@0: const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice); sl@0: TUint32* scanLineBuffer = drawDevice->ScanLineBuffer(); sl@0: sl@0: for (TInt row = y1; row != y2; row += yinc) sl@0: { sl@0: drawDevice->ReadLine(rect.iTl.iX,row,width,scanLineBuffer,dispMode); sl@0: drawDevice->WriteLine(xoffset,row + aOffset.iY,width, scanLineBuffer,iDrawMode); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Draws and fills a rectangle. sl@0: sl@0: The function provides a concrete implementation of the pure virtual sl@0: function CGraphicsContext::DrawRect(). The function sl@0: behaviour is the same as documented in that class. sl@0: */ sl@0: EXPORT_C void CFbsBitGc::DrawRect(const TRect& aRect) sl@0: { sl@0: if (CheckDevice(aRect)) sl@0: return; sl@0: sl@0: TRect rcpy(aRect); sl@0: TRect clippedBoundingRect(rcpy); sl@0: clippedBoundingRect.Move(iOrigin); sl@0: clippedBoundingRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1); sl@0: if(!clippedBoundingRect.Intersects(iUserClipRect)) sl@0: return; sl@0: sl@0: CGraphicsAccelerator* ga = GraphicsAccelerator(); sl@0: sl@0: SetupDevice(); sl@0: iDevice->DrawingBegin(); sl@0: iBrushBitmap.BeginDataAccess(); sl@0: CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap); sl@0: sl@0: if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1 && iPenStyle != 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 != ESolidPen) sl@0: iDotParam = 0; sl@0: sl@0: if (width) 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: 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: if (width && height > 1) 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: if (height > 2) sl@0: DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left 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: goto nofill; sl@0: sl@0: rcpy.Shrink(1,1); sl@0: rcpy.Move(iOrigin); sl@0: } sl@0: else if (iPenStyle != ENullPen && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1)) sl@0: { sl@0: rcpy.Move(iOrigin); sl@0: sl@0: const TBrushStyle tempbrushstyle = iBrushStyle; sl@0: iBrushStyle = ESolidBrush; sl@0: const TRgb tempbrushColor = iBrushColor; sl@0: iBrushColor = iPenColor; sl@0: const CGraphicsContext::TDrawMode tempdrawmode = iDrawMode; sl@0: sl@0: if(iDrawMode != CGraphicsContext::EDrawModeWriteAlpha) sl@0: { sl@0: iDrawMode = CGraphicsContext::EDrawModePEN; sl@0: } 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: rcpy.iTl.iX -= halfpenwidth; sl@0: rcpy.iTl.iY -= halfpenheight; sl@0: rcpy.iBr.iX += otherhalfwidth; sl@0: rcpy.iBr.iY += otherhalfheight; sl@0: sl@0: RectFill(rcpy); sl@0: sl@0: iBrushStyle = tempbrushstyle; sl@0: iBrushColor = tempbrushColor; sl@0: iDrawMode = tempdrawmode; sl@0: sl@0: goto nofill; sl@0: } sl@0: else 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: rcpy.iTl.iX += otherhalfwidth; sl@0: rcpy.iTl.iY += otherhalfheight; sl@0: rcpy.iBr.iX -= halfpenwidth; sl@0: rcpy.iBr.iY -= halfpenheight; sl@0: sl@0: iBrushStyle = tempbrushstyle; sl@0: iBrushColor = tempbrushColor; sl@0: iDrawMode = tempdrawmode; sl@0: } sl@0: } sl@0: else sl@0: rcpy.Move(iOrigin); sl@0: sl@0: //use Graphics accelerator if available sl@0: if(ga) sl@0: { sl@0: TInt i = -1; sl@0: //Draw rect sl@0: if(iPenStyle == ENullPen && iShadowMode == CFbsDrawDevice::ENoShadow) sl@0: { sl@0: if(iBrushStyle == ESolidBrush ) sl@0: { sl@0: // EDrawModePEN and EDrawModeWriteAlpha mode should use the same method when sl@0: // (1) solid brush with opaque color is used. Or sl@0: // (2) solid brush with transparent color is used but display mode is sl@0: // other than EColor64K, EColor16MU, EColor16MA, EColor16MAP. sl@0: // in the same way as the software implemantation does and calls WriteRgbMulti method. sl@0: if(iDrawMode == EDrawModeWriteAlpha) sl@0: { sl@0: i = 0; sl@0: } sl@0: else if(iDrawMode == EDrawModePEN) sl@0: { sl@0: if(iBrushColor.Alpha() == 255) sl@0: { sl@0: i = 0; sl@0: } sl@0: else sl@0: { sl@0: TDisplayMode dispMode = iDevice->DisplayMode(); sl@0: if(dispMode != EColor64K && dispMode != EColor16MU && dispMode != EColor16MA && dispMode != EColor16MAP) sl@0: { sl@0: i = 0; sl@0: } sl@0: } sl@0: } sl@0: //Invert color sl@0: else if(iDrawMode == EDrawModeNOTSCREEN) sl@0: { sl@0: i = 1; sl@0: } sl@0: } sl@0: //use a patter brush sl@0: else if(iBrushStyle == EPatternedBrush) sl@0: { sl@0: i = 2; sl@0: } sl@0: } sl@0: sl@0: if(i != -1) sl@0: { sl@0: TInt gaOperationResult = KErrUnknown; sl@0: iDevice->DrawingEnd(); sl@0: sl@0: const TInt limit=iDefaultRegionPtr->Count(); sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: iClipRect = (*iDefaultRegionPtr)[count]; sl@0: if (!iClipRect.Intersects(rcpy)) sl@0: continue; sl@0: sl@0: iClipRect.Intersection(rcpy); sl@0: if (UserClipRect(iClipRect)) sl@0: continue; sl@0: sl@0: switch(i) sl@0: { sl@0: case 0: sl@0: gaOperationResult = ga->Operation(TGopFilledRect(iClipRect,iBrushColor)); sl@0: break; sl@0: case 1: sl@0: gaOperationResult = ga->Operation(TGopInvertRect(iClipRect)); sl@0: break; sl@0: case 2: sl@0: CFbsBitmap* brushbitmap = (CFbsBitmap*)&iBrushBitmap; sl@0: BG_ASSERT_ALWAYS(iBrushUsed,EBitgdiPanicInvalidBitmap); sl@0: BG_ASSERT_ALWAYS(brushbitmap != NULL,EBitgdiPanicInvalidBitmap); sl@0: sl@0: TAcceleratedBitmapSpec brushBitmapSpec(brushbitmap); sl@0: TGopFillPattern gopFillPattern; sl@0: gopFillPattern.iBitmap = brushBitmapSpec; sl@0: gopFillPattern.iOrigin = iBrushOrigin; sl@0: gaOperationResult = ga->Operation(TGopFilledRectWithPattern(iClipRect,gopFillPattern)); sl@0: break; sl@0: } sl@0: if(gaOperationResult != KErrNone) sl@0: break; sl@0: } sl@0: if(gaOperationResult == KErrNone) sl@0: goto finish; sl@0: iDevice->DrawingBegin(); sl@0: } sl@0: } sl@0: sl@0: RectFill(rcpy); sl@0: sl@0: nofill: sl@0: iDevice->DrawingEnd(); sl@0: finish: sl@0: if (brushRasterizer) sl@0: { sl@0: brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber()); sl@0: } sl@0: iBrushBitmap.EndDataAccess(ETrue); sl@0: } sl@0: sl@0: // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method sl@0: void CFbsBitGc::RectFill(const TRect& aRect) sl@0: { sl@0: if (aRect.IsEmpty() || iBrushStyle == ENullBrush) sl@0: return; sl@0: sl@0: CFbsDrawDevice* drawDevice = iDevice->iDrawDevice; sl@0: sl@0: AddRect(aRect); sl@0: sl@0: const TPoint origin = iOrigin + iBrushOrigin; sl@0: sl@0: const TInt limit=iDefaultRegionPtr->Count(); sl@0: for (TInt count = 0; count < limit; count++) sl@0: { sl@0: iClipRect = (*iDefaultRegionPtr)[count]; sl@0: if (!iClipRect.Intersects(aRect)) sl@0: continue; sl@0: sl@0: iClipRect.Intersection(aRect); sl@0: if (UserClipRect(iClipRect)) sl@0: continue; sl@0: sl@0: #ifdef _DEBUG sl@0: TRect deviceRect; sl@0: drawDevice->GetDrawRect(deviceRect); sl@0: #endif sl@0: BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds); sl@0: BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds); sl@0: sl@0: TInt xcoord = iClipRect.iTl.iX; sl@0: TInt ycoord = iClipRect.iTl.iY; sl@0: sl@0: sl@0: switch(iBrushStyle) sl@0: { sl@0: case ESolidBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: break; sl@0: case EPatternedBrush: sl@0: { sl@0: CBitwiseBitmap* brushbitmap = iBrushBitmap.Address(); sl@0: BG_ASSERT_ALWAYS(iBrushUsed,EBitgdiPanicInvalidBitmap); sl@0: BG_ASSERT_ALWAYS(brushbitmap != NULL,EBitgdiPanicInvalidBitmap); sl@0: sl@0: TRect sourcerect(iClipRect); sl@0: sourcerect.Move(-origin); sl@0: DoBitBlt(iClipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect); sl@0: break; sl@0: } sl@0: case EHorizontalHatchBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: while (Abs((ycoord - origin.iY) % 3) != 2) sl@0: ycoord++; sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord += 3) sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,ycoord,iClipRect.Width(),1,iPenColor,iDrawMode); sl@0: break; sl@0: case EVerticalHatchBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgbMulti(xcoord,iClipRect.iTl.iY,1,iClipRect.Height(),iPenColor,iDrawMode); sl@0: break; sl@0: case ESquareCrossHatchBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: while (Abs((ycoord - origin.iY) % 3) != 2) sl@0: ycoord++; sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord += 3) // horizontal lines sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,ycoord,iClipRect.Width(),1,iPenColor,iDrawMode); sl@0: sl@0: ycoord = iClipRect.iTl.iY; sl@0: while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < iClipRect.iBr.iY) // above the top horizontal line sl@0: { sl@0: xcoord = iClipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode); sl@0: ycoord++; sl@0: } sl@0: sl@0: ycoord += 3; sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals sl@0: { sl@0: xcoord = iClipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,iDrawMode); sl@0: } sl@0: sl@0: ycoord -= 3; sl@0: while (ycoord < iClipRect.iBr.iY) // below the bottom horizontal sl@0: { sl@0: xcoord = iClipRect.iTl.iX; sl@0: while (Abs((xcoord - origin.iX) % 3) != 2) sl@0: xcoord++; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode); sl@0: ycoord++; sl@0: } sl@0: break; sl@0: case EForwardDiagonalHatchBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord++) sl@0: { sl@0: xcoord = iClipRect.iTl.iX; sl@0: TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3; sl@0: if (diff < 0) sl@0: diff += 3; sl@0: xcoord += diff; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode); sl@0: } sl@0: break; sl@0: case ERearwardDiagonalHatchBrush: sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord++) sl@0: { sl@0: xcoord = iClipRect.iTl.iX; sl@0: TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3; sl@0: if (diff < 0) sl@0: diff += 3; sl@0: xcoord += diff; sl@0: for (; xcoord < iClipRect.iBr.iX; xcoord += 3) sl@0: drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode); sl@0: } sl@0: break; sl@0: case EDiamondCrossHatchBrush: sl@0: { sl@0: drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY, sl@0: iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode); sl@0: TInt sum = xcoord + ycoord - origin.iX - origin.iY; sl@0: for (; ycoord < iClipRect.iBr.iY; ycoord++,sum++) sl@0: { sl@0: TInt currentsum = sum; sl@0: for (xcoord = iClipRect.iTl.iX; xcoord < iClipRect.iBr.iX; xcoord++,currentsum++) sl@0: { sl@0: if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1)) sl@0: drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode); sl@0: } sl@0: } sl@0: break; sl@0: } sl@0: default: sl@0: return; sl@0: } sl@0: sl@0: drawDevice->UpdateRegion(iClipRect); sl@0: } sl@0: } sl@0: