First public contribution.
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <graphicsaccelerator.h>
23 #include <graphics/fbsrasterizer.h>
28 The function provides a concrete implementation of the pure virtual
29 function <code>CBitmapContext::CopyRect()</code>. The function
30 behaviour is the same as documented in that class.
32 EXPORT_C void CFbsBitGc::CopyRect(const TPoint& aOffset,const TRect& aRect)
34 if(CheckDevice(aRect) || aRect.IsEmpty() || aOffset == TPoint(0,0))
37 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
40 drawDevice->GetDrawRect(deviceRect);
41 const TPoint back(TPoint(0,0)-aOffset);
44 rcpy.Intersection(deviceRect);
45 ((TRegion*)iDefaultRegionPtr)->Sort(aOffset);
47 TRect clippedBoundingRect(rcpy);
48 clippedBoundingRect.Move(aOffset);
49 AddRect(clippedBoundingRect);
50 clippedBoundingRect.BoundingRect(rcpy);
51 if(!clippedBoundingRect.Intersects(iUserClipRect))
55 iDevice->DrawingBegin();
57 const TInt limit=iDefaultRegionPtr->Count();
58 for(TInt count=0;count<limit;count++)
60 iClipRect=(*iDefaultRegionPtr)[count];
61 if(UserClipRect(iClipRect))
64 if(!iClipRect.Intersects(rcpy))
67 iClipRect.Intersection(rcpy);
68 TDrawMode drawMode = iDrawMode;
69 iDrawMode = EDrawModeWriteAlpha;
70 DoCopyRect(aOffset,iClipRect);
71 iDrawMode = drawMode; // restore the previous draw mode
72 iClipRect.Move(aOffset);
73 drawDevice->UpdateRegion(iClipRect);
76 iDevice->DrawingEnd();
79 void CFbsBitGc::DoCopyRect(const TPoint& aOffset,const TRect& rect)
81 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
84 drawDevice->GetDrawRect(deviceRect);
86 BG_ASSERT_DEBUG(rect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
87 BG_ASSERT_DEBUG(rect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
88 BG_ASSERT_DEBUG(rect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
89 BG_ASSERT_DEBUG(rect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
92 offrect.Move(aOffset);
94 BG_ASSERT_DEBUG(offrect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
95 BG_ASSERT_DEBUG(offrect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
96 BG_ASSERT_DEBUG(offrect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
97 BG_ASSERT_DEBUG(offrect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
99 TInt y1 = rect.iTl.iY,y2 = rect.iBr.iY,yinc = 1; // default y2>y1
100 if (aOffset.iY > 0) // y1>y2
102 y1 = rect.iBr.iY - 1;
103 y2 = rect.iTl.iY - 1;
107 const TInt width = rect.Width();
108 const TInt xoffset = rect.iTl.iX + aOffset.iX;
109 const TDisplayMode dispMode = ScanLineBufferDisplayMode(drawDevice);
110 TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
112 for (TInt row = y1; row != y2; row += yinc)
114 drawDevice->ReadLine(rect.iTl.iX,row,width,scanLineBuffer,dispMode);
115 drawDevice->WriteLine(xoffset,row + aOffset.iY,width, scanLineBuffer,iDrawMode);
120 Draws and fills a rectangle.
122 The function provides a concrete implementation of the pure virtual
123 function <code>CGraphicsContext::DrawRect()</code>. The function
124 behaviour is the same as documented in that class.
126 EXPORT_C void CFbsBitGc::DrawRect(const TRect& aRect)
128 if (CheckDevice(aRect))
132 TRect clippedBoundingRect(rcpy);
133 clippedBoundingRect.Move(iOrigin);
134 clippedBoundingRect.Grow((iPenSize.iWidth >> 1) + 1,(iPenSize.iHeight >> 1) + 1);
135 if(!clippedBoundingRect.Intersects(iUserClipRect))
138 CGraphicsAccelerator* ga = GraphicsAccelerator();
141 iDevice->DrawingBegin();
142 iBrushBitmap.BeginDataAccess();
143 CFbsRasterizer* brushRasterizer = PrepareRasterizerForExtendedBitmap(iBrushBitmap);
145 if (iPenSize.iWidth == 1 && iPenSize.iHeight == 1 && iPenStyle != ENullPen)
147 const TInt width = rcpy.Width();
148 const TInt height = rcpy.Height();
149 const TPoint currentLinePosition = iLinePosition;
151 if (iPenStyle != ESolidPen)
155 DoDrawLine(rcpy.iTl,TPoint(rcpy.iBr.iX,rcpy.iTl.iY),ETrue); // top
157 if (height > 2 && width > 1)
158 DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iTl.iY+1),TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),ETrue); // right
160 if (width && height > 1)
161 DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),TPoint(rcpy.iTl.iX-1,rcpy.iBr.iY-1),ETrue); // bottom
164 DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left
166 // Restore internal line position in case it has been modified by DoDrawLine().
167 // DrawRect() should not be modifying it.
168 iLinePosition = currentLinePosition;
170 if (width < 3 || height < 3)
176 else if (iPenStyle != ENullPen && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1))
180 const TBrushStyle tempbrushstyle = iBrushStyle;
181 iBrushStyle = ESolidBrush;
182 const TRgb tempbrushColor = iBrushColor;
183 iBrushColor = iPenColor;
184 const CGraphicsContext::TDrawMode tempdrawmode = iDrawMode;
186 if(iDrawMode != CGraphicsContext::EDrawModeWriteAlpha)
188 iDrawMode = CGraphicsContext::EDrawModePEN;
191 const TInt halfpenwidth = (iPenSize.iWidth - 1) >> 1;
192 const TInt halfpenheight = (iPenSize.iHeight - 1) >> 1;
193 const TInt otherhalfwidth = (iPenSize.iWidth >> 1) + 1;
194 const TInt otherhalfheight = (iPenSize.iHeight >> 1) + 1;
199 if (rcpy.iBr.iY - rcpy.iTl.iY <= iPenSize.iHeight + 1 || rcpy.iBr.iX - rcpy.iTl.iX <= iPenSize.iWidth + 1)
201 rcpy.iTl.iX -= halfpenwidth;
202 rcpy.iTl.iY -= halfpenheight;
203 rcpy.iBr.iX += otherhalfwidth;
204 rcpy.iBr.iY += otherhalfheight;
208 iBrushStyle = tempbrushstyle;
209 iBrushColor = tempbrushColor;
210 iDrawMode = tempdrawmode;
216 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iTl.iY + otherhalfheight)); // top
217 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iTl.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // left
218 RectFill(TRect(rcpy.iBr.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // right
219 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iBr.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY + otherhalfheight)); // bottom
221 rcpy.iTl.iX += otherhalfwidth;
222 rcpy.iTl.iY += otherhalfheight;
223 rcpy.iBr.iX -= halfpenwidth;
224 rcpy.iBr.iY -= halfpenheight;
226 iBrushStyle = tempbrushstyle;
227 iBrushColor = tempbrushColor;
228 iDrawMode = tempdrawmode;
234 //use Graphics accelerator if available
239 if(iPenStyle == ENullPen && iShadowMode == CFbsDrawDevice::ENoShadow)
241 if(iBrushStyle == ESolidBrush )
243 // EDrawModePEN and EDrawModeWriteAlpha mode should use the same method when
244 // (1) solid brush with opaque color is used. Or
245 // (2) solid brush with transparent color is used but display mode is
246 // other than EColor64K, EColor16MU, EColor16MA, EColor16MAP.
247 // in the same way as the software implemantation does and calls WriteRgbMulti method.
248 if(iDrawMode == EDrawModeWriteAlpha)
252 else if(iDrawMode == EDrawModePEN)
254 if(iBrushColor.Alpha() == 255)
260 TDisplayMode dispMode = iDevice->DisplayMode();
261 if(dispMode != EColor64K && dispMode != EColor16MU && dispMode != EColor16MA && dispMode != EColor16MAP)
268 else if(iDrawMode == EDrawModeNOTSCREEN)
274 else if(iBrushStyle == EPatternedBrush)
282 TInt gaOperationResult = KErrUnknown;
283 iDevice->DrawingEnd();
285 const TInt limit=iDefaultRegionPtr->Count();
286 for (TInt count = 0; count < limit; count++)
288 iClipRect = (*iDefaultRegionPtr)[count];
289 if (!iClipRect.Intersects(rcpy))
292 iClipRect.Intersection(rcpy);
293 if (UserClipRect(iClipRect))
299 gaOperationResult = ga->Operation(TGopFilledRect(iClipRect,iBrushColor));
302 gaOperationResult = ga->Operation(TGopInvertRect(iClipRect));
305 CFbsBitmap* brushbitmap = (CFbsBitmap*)&iBrushBitmap;
306 BG_ASSERT_ALWAYS(iBrushUsed,EBitgdiPanicInvalidBitmap);
307 BG_ASSERT_ALWAYS(brushbitmap != NULL,EBitgdiPanicInvalidBitmap);
309 TAcceleratedBitmapSpec brushBitmapSpec(brushbitmap);
310 TGopFillPattern gopFillPattern;
311 gopFillPattern.iBitmap = brushBitmapSpec;
312 gopFillPattern.iOrigin = iBrushOrigin;
313 gaOperationResult = ga->Operation(TGopFilledRectWithPattern(iClipRect,gopFillPattern));
316 if(gaOperationResult != KErrNone)
319 if(gaOperationResult == KErrNone)
321 iDevice->DrawingBegin();
328 iDevice->DrawingEnd();
332 brushRasterizer->EndBitmap(iBrushBitmap.SerialNumber());
334 iBrushBitmap.EndDataAccess(ETrue);
337 // if iBrushBitmap is an extended bitmap, PrepareRasterizerForExtendedBitmap() must have been called before this method
338 void CFbsBitGc::RectFill(const TRect& aRect)
340 if (aRect.IsEmpty() || iBrushStyle == ENullBrush)
343 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
347 const TPoint origin = iOrigin + iBrushOrigin;
349 const TInt limit=iDefaultRegionPtr->Count();
350 for (TInt count = 0; count < limit; count++)
352 iClipRect = (*iDefaultRegionPtr)[count];
353 if (!iClipRect.Intersects(aRect))
356 iClipRect.Intersection(aRect);
357 if (UserClipRect(iClipRect))
362 drawDevice->GetDrawRect(deviceRect);
364 BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceRect.iTl.iX, EBitgdiPanicOutOfBounds);
365 BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceRect.iTl.iY, EBitgdiPanicOutOfBounds);
366 BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceRect.iBr.iX, EBitgdiPanicOutOfBounds);
367 BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceRect.iBr.iY, EBitgdiPanicOutOfBounds);
369 TInt xcoord = iClipRect.iTl.iX;
370 TInt ycoord = iClipRect.iTl.iY;
376 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
377 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
379 case EPatternedBrush:
381 CBitwiseBitmap* brushbitmap = iBrushBitmap.Address();
382 BG_ASSERT_ALWAYS(iBrushUsed,EBitgdiPanicInvalidBitmap);
383 BG_ASSERT_ALWAYS(brushbitmap != NULL,EBitgdiPanicInvalidBitmap);
385 TRect sourcerect(iClipRect);
386 sourcerect.Move(-origin);
387 DoBitBlt(iClipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect);
390 case EHorizontalHatchBrush:
391 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
392 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
393 while (Abs((ycoord - origin.iY) % 3) != 2)
395 for (; ycoord < iClipRect.iBr.iY; ycoord += 3)
396 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,ycoord,iClipRect.Width(),1,iPenColor,iDrawMode);
398 case EVerticalHatchBrush:
399 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
400 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
401 while (Abs((xcoord - origin.iX) % 3) != 2)
403 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
404 drawDevice->WriteRgbMulti(xcoord,iClipRect.iTl.iY,1,iClipRect.Height(),iPenColor,iDrawMode);
406 case ESquareCrossHatchBrush:
407 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
408 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
409 while (Abs((ycoord - origin.iY) % 3) != 2)
411 for (; ycoord < iClipRect.iBr.iY; ycoord += 3) // horizontal lines
412 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,ycoord,iClipRect.Width(),1,iPenColor,iDrawMode);
414 ycoord = iClipRect.iTl.iY;
415 while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < iClipRect.iBr.iY) // above the top horizontal line
417 xcoord = iClipRect.iTl.iX;
418 while (Abs((xcoord - origin.iX) % 3) != 2)
420 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
421 drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode);
426 for (; ycoord < iClipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals
428 xcoord = iClipRect.iTl.iX;
429 while (Abs((xcoord - origin.iX) % 3) != 2)
431 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
432 drawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,iDrawMode);
436 while (ycoord < iClipRect.iBr.iY) // below the bottom horizontal
438 xcoord = iClipRect.iTl.iX;
439 while (Abs((xcoord - origin.iX) % 3) != 2)
441 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
442 drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode);
446 case EForwardDiagonalHatchBrush:
447 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
448 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
449 for (; ycoord < iClipRect.iBr.iY; ycoord++)
451 xcoord = iClipRect.iTl.iX;
452 TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3;
456 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
457 drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode);
460 case ERearwardDiagonalHatchBrush:
461 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
462 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
463 for (; ycoord < iClipRect.iBr.iY; ycoord++)
465 xcoord = iClipRect.iTl.iX;
466 TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3;
470 for (; xcoord < iClipRect.iBr.iX; xcoord += 3)
471 drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode);
474 case EDiamondCrossHatchBrush:
476 drawDevice->WriteRgbMulti(iClipRect.iTl.iX,iClipRect.iTl.iY,
477 iClipRect.Width(),iClipRect.Height(),iBrushColor,iDrawMode);
478 TInt sum = xcoord + ycoord - origin.iX - origin.iY;
479 for (; ycoord < iClipRect.iBr.iY; ycoord++,sum++)
481 TInt currentsum = sum;
482 for (xcoord = iClipRect.iTl.iX; xcoord < iClipRect.iBr.iX; xcoord++,currentsum++)
484 if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1))
485 drawDevice->WriteRgb(xcoord,ycoord,iPenColor,iDrawMode);
494 drawDevice->UpdateRegion(iClipRect);