os/graphics/graphicsdeviceinterface/directgdiadaptation/swsrc/swdirectgdirect.cpp
Update contrib.
1 // Copyright (c) 2007-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.
16 #include "directgdiadapter.h"
17 #include "swdirectgdiengine.h"
20 @see MDirectGdiEngine::CopyRect()
22 void CSwDirectGdiEngine::CopyRect(const TPoint& aOffset, const TRect& aRect)
25 iDrawDevice->GetDrawRect(deviceRect);
26 const TPoint back(TPoint(0,0) - aOffset);
29 rcpy.Intersection(deviceRect);
30 ((TRegion*)iDefaultRegionPtr)->Sort(aOffset);
32 TRect targetRect(rcpy);
33 targetRect.Move(aOffset);
34 targetRect.BoundingRect(rcpy);
36 TRect clipRect(0,0,0,0);
37 const TInt limit = iDefaultRegionPtr->Count();
38 for(TInt count = 0; count < limit; count++)
40 clipRect = (*iDefaultRegionPtr)[count];
43 if (!clipRect.Intersects(rcpy))
48 clipRect.Intersection(rcpy);
49 DirectGdi::TDrawMode drawMode = iDrawMode;
50 iDrawMode = DirectGdi::EDrawModeWriteAlpha;
51 DoCopyRect(aOffset, clipRect);
52 iDrawMode = drawMode; // restore the previous draw mode
53 clipRect.Move(aOffset);
54 iDrawDevice->UpdateRegion(clipRect);
60 @panic DGDIAdapter 1013, if aRect or aOffset are outside of the destination bounds (debug only).
62 void CSwDirectGdiEngine::DoCopyRect(const TPoint& aOffset, const TRect& aRect)
66 iDrawDevice->GetDrawRect(deviceRect);
68 GRAPHICS_ASSERT_DEBUG(aRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
69 GRAPHICS_ASSERT_DEBUG(aRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
70 GRAPHICS_ASSERT_DEBUG(aRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
71 GRAPHICS_ASSERT_DEBUG(aRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
73 TRect offsetRect(aRect);
74 offsetRect.Move(aOffset);
76 GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
77 GRAPHICS_ASSERT_DEBUG(offsetRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
78 GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
79 GRAPHICS_ASSERT_DEBUG(offsetRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
81 TInt y1 = aRect.iTl.iY;
82 TInt y2 = aRect.iBr.iY;
83 TInt yinc = 1; // default y2>y1
84 if (aOffset.iY > 0) // y1>y2
86 y1 = aRect.iBr.iY - 1;
87 y2 = aRect.iTl.iY - 1;
91 const TInt width = aRect.Width();
92 const TInt xoffset = aRect.iTl.iX + aOffset.iX;
93 const TDisplayMode dispMode = ScanLineBufferDisplayMode(iDrawDevice);
94 TUint32* scanLineBuffer = iDrawDevice->ScanLineBuffer();
96 for (TInt row = y1; row != y2; row += yinc)
98 iDrawDevice->ReadLine(aRect.iTl.iX, row, width, scanLineBuffer, dispMode);
99 iDrawDevice->WriteLine(xoffset, row + aOffset.iY, width, scanLineBuffer, GcDrawMode(iDrawMode));
104 @see MDirectGdiEngine::DrawRect()
106 void CSwDirectGdiEngine::DrawRect(const TRect& aRect)
110 iBrushBitmap.BeginDataAccess();
112 if ((iPenSize.iWidth == 1) && (iPenSize.iHeight == 1) && iPenStyle != DirectGdi::ENullPen)
114 const TInt width = rcpy.Width();
115 const TInt height = rcpy.Height();
116 const TPoint currentLinePosition = iLinePosition;
118 if (iPenStyle != DirectGdi::ESolidPen)
123 DoDrawLine(rcpy.iTl,TPoint(rcpy.iBr.iX,rcpy.iTl.iY),ETrue); // top
125 if (height > 2 && width > 1)
127 DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iTl.iY+1),TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),ETrue); // right
132 DoDrawLine(TPoint(rcpy.iBr.iX-1,rcpy.iBr.iY-1),TPoint(rcpy.iTl.iX-1,rcpy.iBr.iY-1),ETrue); // bottom
137 DoDrawLine(TPoint(rcpy.iTl.iX,rcpy.iBr.iY-2),rcpy.iTl,ETrue); // left
140 // Restore internal line position in case it has been modified by DoDrawLine().
141 // DrawRect() should not be modifying it.
142 iLinePosition = currentLinePosition;
144 if (width < 3 || height < 3)
152 else if ((iPenStyle != DirectGdi::ENullPen) && (iPenSize.iWidth >= 1 && iPenSize.iHeight >= 1))
156 const DirectGdi::TBrushStyle tempbrushstyle = iBrushStyle;
157 const TRgb tempbrushColor = iBrushColor;
158 const DirectGdi::TDrawMode tempdrawmode = iDrawMode;
160 const TInt halfpenwidth = (iPenSize.iWidth - 1) >> 1;
161 const TInt halfpenheight = (iPenSize.iHeight - 1) >> 1;
162 const TInt otherhalfwidth = (iPenSize.iWidth >> 1) + 1;
163 const TInt otherhalfheight = (iPenSize.iHeight >> 1) + 1;
168 if (((rcpy.iBr.iY - rcpy.iTl.iY) <= (iPenSize.iHeight + 1)) || ((rcpy.iBr.iX - rcpy.iTl.iX) <= (iPenSize.iWidth + 1)))
170 iBrushColor = iPenColor;
171 iBrushStyle = DirectGdi::ESolidBrush;
172 if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
174 iDrawMode = DirectGdi::EDrawModePEN;
177 rcpy.iTl.iX -= halfpenwidth;
178 rcpy.iTl.iY -= halfpenheight;
179 rcpy.iBr.iX += otherhalfwidth;
180 rcpy.iBr.iY += otherhalfheight;
185 // In the event the pen outline is semi-transparent, we must do the fill first so that the
186 // outline is blended over the top.
189 iBrushColor = iPenColor;
190 iBrushStyle = DirectGdi::ESolidBrush;
191 if(iDrawMode != DirectGdi::EDrawModeWriteAlpha)
193 iDrawMode = DirectGdi::EDrawModePEN;
195 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iTl.iY + otherhalfheight)); // top
196 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iTl.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // left
197 RectFill(TRect(rcpy.iBr.iX - halfpenwidth,rcpy.iTl.iY + otherhalfheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY - halfpenheight)); // right
198 RectFill(TRect(rcpy.iTl.iX - halfpenwidth,rcpy.iBr.iY - halfpenheight,rcpy.iBr.iX + otherhalfwidth,rcpy.iBr.iY + otherhalfheight)); // bottom
201 iBrushStyle = tempbrushstyle;
202 iBrushColor = tempbrushColor;
203 iDrawMode = tempdrawmode;
214 iBrushBitmap.EndDataAccess(ETrue);
218 Fills the given area using the current brush.
220 @param aRect The area to fill.
221 @panic DGDIAdapter 1013, if the a clipping rectangle is fully outside of the destination bounds (debug only).
222 @panic DGDIAdapter 7, if using EPatternedBrush with no brush pattern bitmap.
224 void CSwDirectGdiEngine::RectFill(const TRect& aRect)
226 if (aRect.IsEmpty() || iBrushStyle == DirectGdi::ENullBrush)
231 const TPoint origin = iOrigin + iBrushOrigin;
232 const TInt limit = iDefaultRegionPtr->Count();
233 TRect clipRect(0,0,0,0);
234 for (TInt count = 0; count < limit; count++)
236 clipRect = (*iDefaultRegionPtr)[count];
237 if (!clipRect.Intersects(aRect))
242 clipRect.Intersection(aRect);
246 iDrawDevice->GetDrawRect(deviceRect);
247 GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iX >= deviceRect.iTl.iX, EDirectGdiPanicOutOfBounds);
248 GRAPHICS_ASSERT_DEBUG(clipRect.iTl.iY >= deviceRect.iTl.iY, EDirectGdiPanicOutOfBounds);
249 GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iX <= deviceRect.iBr.iX, EDirectGdiPanicOutOfBounds);
250 GRAPHICS_ASSERT_DEBUG(clipRect.iBr.iY <= deviceRect.iBr.iY, EDirectGdiPanicOutOfBounds);
253 TInt xcoord = clipRect.iTl.iX;
254 TInt ycoord = clipRect.iTl.iY;
255 const CGraphicsContext::TDrawMode drawMode = GcDrawMode(iDrawMode);
259 case DirectGdi::ESolidBrush:
260 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
261 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
263 case DirectGdi::EPatternedBrush:
265 iBrushBitmap.BeginDataAccess();
266 CBitwiseBitmap* brushbitmap = iBrushBitmap.Address();
268 GRAPHICS_ASSERT_ALWAYS(brushbitmap != NULL, EDirectGdiPanicInvalidBitmap);
270 TRect sourcerect(clipRect);
271 sourcerect.Move(-origin);
273 DoBitBlt(clipRect.iTl,brushbitmap,iBrushBitmap.DataAddress(),iBrushBitmap.DataStride(),sourcerect);
274 iBrushBitmap.EndDataAccess(ETrue);
277 case DirectGdi::EHorizontalHatchBrush:
278 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
279 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
280 while (Abs((ycoord - origin.iY) % 3) != 2)
284 for (; ycoord < clipRect.iBr.iY; ycoord += 3)
286 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
289 case DirectGdi::EVerticalHatchBrush:
290 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
291 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
292 while (Abs((xcoord - origin.iX) % 3) != 2)
296 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
298 iDrawDevice->WriteRgbMulti(xcoord,clipRect.iTl.iY,1,clipRect.Height(),iPenColor,drawMode);
301 case DirectGdi::ESquareCrossHatchBrush:
302 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
303 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
304 while (Abs((ycoord - origin.iY) % 3) != 2)
308 for (; ycoord < clipRect.iBr.iY; ycoord += 3) // horizontal lines
310 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,ycoord,clipRect.Width(),1,iPenColor,drawMode);
313 ycoord = clipRect.iTl.iY;
314 while (Abs((ycoord - origin.iY) % 3) != 2 && ycoord < clipRect.iBr.iY) // above the top horizontal line
316 xcoord = clipRect.iTl.iX;
317 while (Abs((xcoord - origin.iX) % 3) != 2)
321 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
323 iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
328 for (; ycoord < clipRect.iBr.iY; ycoord += 3) // between the top and bottom horizontals
330 xcoord = clipRect.iTl.iX;
331 while (Abs((xcoord - origin.iX) % 3) != 2)
335 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
337 iDrawDevice->WriteRgbMulti(xcoord,ycoord - 2,1,2,iPenColor,drawMode);
342 while (ycoord < clipRect.iBr.iY) // below the bottom horizontal
344 xcoord = clipRect.iTl.iX;
345 while (Abs((xcoord - origin.iX) % 3) != 2)
349 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
351 iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
356 case DirectGdi::EForwardDiagonalHatchBrush:
357 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
358 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
359 for (; ycoord < clipRect.iBr.iY; ycoord++)
361 xcoord = clipRect.iTl.iX;
362 TInt diff = (origin.iX + origin.iY - xcoord - ycoord) % 3;
368 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
370 iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
374 case DirectGdi::ERearwardDiagonalHatchBrush:
375 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
376 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
377 for (; ycoord < clipRect.iBr.iY; ycoord++)
379 xcoord = clipRect.iTl.iX;
380 TInt diff = (origin.iX - origin.iY - xcoord + ycoord) % 3;
386 for (; xcoord < clipRect.iBr.iX; xcoord += 3)
388 iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
392 case DirectGdi::EDiamondCrossHatchBrush:
394 iDrawDevice->WriteRgbMulti(clipRect.iTl.iX,clipRect.iTl.iY,
395 clipRect.Width(),clipRect.Height(),iBrushColor,drawMode);
396 TInt sum = xcoord + ycoord - origin.iX - origin.iY;
397 for (; ycoord < clipRect.iBr.iY; ycoord++,sum++)
399 TInt currentsum = sum;
400 for (xcoord = clipRect.iTl.iX; xcoord < clipRect.iBr.iX; xcoord++,currentsum++)
402 if((currentsum & 1) == 0 && ((currentsum & 3) != 0 || ((xcoord-origin.iX) & 1) == 1))
404 iDrawDevice->WriteRgb(xcoord,ycoord,iPenColor,drawMode);
414 iDrawDevice->UpdateRegion(clipRect);