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 <bitdrawinterfaceid.h>
22 #include <bmalphablend.h>
24 #include <graphics/fbsrasterizer.h>
25 #include <graphics/bitmap.inl>
26 #include <graphics/gdi/gdiinline.inl>
31 The function has 3 overloads. The first draws the bitmap given the top
32 left hand corner, doing a compress/stretch based on its internally
33 stored size in twips. The second does a compress/stretch to fit a
34 given rectangle. The third takes a rectangular section of the source
35 bitmap and does a compress/stretch to fit a given destination
36 rectangle.The functions provide a concrete implementation of the pure
37 virtual function <code>CGraphicsContext::DrawBitmap()</code>. The
38 function behaviour is the same as documented in that class.
40 EXPORT_C void CFbsBitGc::DrawBitmap(const TPoint& aPos,const CFbsBitmap* aSource)
42 if (aSource == NULL || !aSource->Handle())
45 aSource->BeginDataAccess();
46 const TSize bitmapTwips = aSource->SizeInTwips();
47 if (bitmapTwips.iWidth == 0 || bitmapTwips.iHeight == 0)
49 aSource->EndDataAccess(ETrue);
54 scrpixels.iWidth = iDevice->HorizontalTwipsToPixels(bitmapTwips.iWidth);
55 scrpixels.iHeight = iDevice->VerticalTwipsToPixels(bitmapTwips.iHeight);
57 DrawBitmap(TRect(aPos, scrpixels), aSource, TRect(aSource->SizeInPixels()));
58 aSource->EndDataAccess(ETrue);
61 EXPORT_C void CFbsBitGc::DrawBitmap(const TRect& aDestRect,const CFbsBitmap* aSource)
63 if (aSource == NULL || !aSource->Handle())
66 aSource->BeginDataAccess();
67 DrawBitmap(aDestRect, aSource, TRect(aSource->SizeInPixels()));
68 aSource->EndDataAccess(ETrue);
71 EXPORT_C void CFbsBitGc::DrawBitmap(const TRect& aDestRect,
72 const CFbsBitmap* aSource,
73 const TRect& aSourceRect)
75 if (CheckDevice(aDestRect) || aSourceRect.IsEmpty() || aSource == NULL || !aSource->Handle())
78 aSource->BeginDataAccess();
79 //aSourceRect should be in the bounds of the bitmap
80 TSize bitmapSize(aSource->SizeInPixels());
81 if ( aSourceRect.iTl.iX < 0
82 || aSourceRect.iTl.iY < 0
83 || aSourceRect.iBr.iX > bitmapSize.iWidth
84 || aSourceRect.iBr.iY > bitmapSize.iHeight)
86 aSource->EndDataAccess(ETrue);
90 TRect destRect(aDestRect);
91 destRect.Move(iOrigin);
94 TRect clippedDestRect(destRect);
95 if (UserClipRect(clippedDestRect))
97 aSource->EndDataAccess(ETrue);
101 CFbsBitGcBitmap* srce = (CFbsBitGcBitmap*)aSource;
103 iDevice->DrawingBegin();
105 CBitwiseBitmap* bmp = srce->Address();
106 BG_ASSERT_DEBUG(bmp,EBitgdiPanicInvalidBitmap);
108 CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aSource, destRect, aSourceRect);
110 const TPoint ditherOrigin(iDitherOrigin + aDestRect.iTl);
112 const TInt limit = iDefaultRegionPtr->Count();
113 CGraphicsAccelerator* ga = GraphicsAccelerator();
114 if (ga && iShadowMode==CFbsDrawDevice::ENoShadow && iDrawMode==EDrawModePEN)
116 TInt gaOperationResult = KErrUnknown;
117 TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aSource));
118 iDevice->DrawingEnd();
120 if (destRect.Size() == aSourceRect.Size())
122 const TPoint offset(aSourceRect.iTl - destRect.iTl);
123 for(TInt count=0;count<limit;count++)
125 iClipRect=(*iDefaultRegionPtr)[count];
126 if(!iClipRect.Intersects(clippedDestRect))
128 iClipRect.Intersection(clippedDestRect);
130 TRect clippedSrceRect(iClipRect);
131 clippedSrceRect.Move(offset);
132 gaOperationResult = ga->Operation(TGopBitBlt(iClipRect.iTl,bitmapSpec,clippedSrceRect));
133 if (gaOperationResult!=KErrNone)
136 iDevice->iDrawDevice->UpdateRegion(iClipRect);
140 RRegion clippedRegion;
141 for(TInt clipIt=0;clipIt<limit;clipIt++)
143 TRect clipRect((*iDefaultRegionPtr)[clipIt]);
144 clipRect.Intersection(clippedDestRect);
145 if (!clipRect.IsEmpty())
146 clippedRegion.AddRect(clipRect);
148 TRect srcCopy(aSourceRect); // Needed because TGopScaledBitBlt takes a non-const value
149 // const_cast needed because Operation takes a non-const region ptr :(
150 gaOperationResult = ga->Operation(TGopScaledBitBlt(destRect,bitmapSpec,srcCopy),clippedRegion.Count(),const_cast<TRect*>(clippedRegion.RectangleList()));
151 if (gaOperationResult==KErrNone)
152 iDevice->iDrawDevice->Update(clippedRegion);
153 clippedRegion.Close();
155 if(gaOperationResult == KErrNone)
157 iDevice->DrawingBegin();
161 { // to stop error from gccxml build about previous jump to finish skipping initialisation of opaqueSource
162 const TBool opaqueSource = (!IsAlphaChannel(aSource->DisplayMode())) && (iDrawMode == EDrawModePEN);
165 iDrawMode = EDrawModeWriteAlpha;
168 for (TInt count = 0; count < limit; count++)
170 iClipRect = (*iDefaultRegionPtr)[count];
171 if (!iClipRect.Intersects(clippedDestRect))
174 iClipRect.Intersection(clippedDestRect);
175 DoDrawBitmap(destRect,bmp,aSource->DataAddress(),aSource->DataStride(),aSourceRect,ditherOrigin);
177 iDevice->iDrawDevice->UpdateRegion(iClipRect);
181 iDrawMode = EDrawModePEN;
185 iDevice->DrawingEnd();
190 rasterizer->EndBitmap(aSource->SerialNumber());
192 aSource->EndDataAccess(ETrue);
196 void CFbsBitGc::DoDrawBitmap(const TRect& aDestRect,
197 CBitwiseBitmap* aBitmap,
200 const TRect& aSrceRect,
201 const TPoint& aDitherOrigin)
203 CFbsDrawDevice* drawDevice = iDevice->iDrawDevice;
205 TRect deviceDestRect;
206 drawDevice->GetDrawRect(deviceDestRect);
208 BG_ASSERT_DEBUG(iClipRect.iTl.iX >= deviceDestRect.iTl.iX, EBitgdiPanicOutOfBounds);
209 BG_ASSERT_DEBUG(iClipRect.iTl.iY >= deviceDestRect.iTl.iY, EBitgdiPanicOutOfBounds);
210 BG_ASSERT_DEBUG(iClipRect.iBr.iX <= deviceDestRect.iBr.iX, EBitgdiPanicOutOfBounds);
211 BG_ASSERT_DEBUG(iClipRect.iBr.iY <= deviceDestRect.iBr.iY, EBitgdiPanicOutOfBounds);
213 if (aDestRect.Size() == aSrceRect.Size())
215 TRect clippedRect(aDestRect);
216 clippedRect.Intersection(iClipRect);
218 if (!clippedRect.IsEmpty())
220 const TPoint destPoint(clippedRect.iTl);
221 clippedRect.Move(aSrceRect.iTl - aDestRect.iTl);
222 DoBitBlt(destPoint,aBitmap,aBase,aStride,clippedRect);
227 MFastBlend* fastBlend=NULL;
228 if (FastBlendInterface(aBitmap,NULL,fastBlend)==KErrNone)
230 if (fastBlend->FastBlendBitmapScaled(iClipRect, aDestRect, aSrceRect, aBase, aStride, aBitmap->DisplayMode(), aBitmap->SizeInPixels(), iDrawMode, iShadowMode)== KErrNone)
236 TUint32* scanLineBuffer = drawDevice->ScanLineBuffer();
237 const TInt scanLineBytes = drawDevice->ScanLineBytes();
238 TPtr8 scanLineDes(REINTERPRET_CAST(TUint8*,scanLineBuffer),scanLineBytes,scanLineBytes);
240 // For EColor16MU targets, don't use EColor16MAP when draw mode is EDrawModeWriteAlpha.
241 // Format conversion provides no performance gain and WriteLine expects EColor16MU
243 const TDisplayMode dispMode = drawDevice->DisplayMode() == EColor16MU && iDrawMode == EDrawModeWriteAlpha ? EColor16MU : drawDevice->ScanLineDisplayMode();
246 TInt bitmapXStart = 0;
247 xLine.Construct(TPoint(aSrceRect.iTl.iX,aDestRect.iTl.iX),
248 TPoint(aSrceRect.iBr.iX,aDestRect.iBr.iX),TLinearDDA::ELeft);
249 xLine.JumpToYCoord(bitmapXStart,iClipRect.iTl.iX);
252 TPoint yCoord(aSrceRect.iTl.iY,aDestRect.iTl.iY);
253 yLine.Construct(yCoord,TPoint(aSrceRect.iBr.iY,aDestRect.iBr.iY),TLinearDDA::ELeft);
255 yLine.JumpToYCoord2(dummy,iClipRect.iTl.iY);
256 yCoord.SetXY(dummy,iClipRect.iTl.iY);
258 TBool finished = EFalse;
259 TPoint ditherOrigin(aDitherOrigin + iClipRect.iTl);
260 const TInt srceWidth = aSrceRect.Width();
261 const TInt destWidth = aDestRect.Width();
262 const TInt clipWidth = iClipRect.Width();
263 const TInt clipStrch = iClipRect.iTl.iX - aDestRect.iTl.iX;
265 TLineScanningPosition lineScanPos(aBase);
266 while (yCoord.iY < iClipRect.iBr.iY && !finished)
268 aBitmap->StretchScanLine(scanLineDes,TPoint(bitmapXStart,yCoord.iX),
269 clipStrch,clipWidth,destWidth,aSrceRect.iTl.iX,
270 srceWidth,ditherOrigin,dispMode,aBase,lineScanPos);
271 if (yCoord.iY==iClipRect.iTl.iY)
272 aBitmap->SetCompressionBookmark(lineScanPos, aBase,NULL);
273 drawDevice->WriteLine(iClipRect.iTl.iX,yCoord.iY,clipWidth, scanLineBuffer,iDrawMode);
274 finished = yLine.NextStep(yCoord);
279 /** The method draws a specified rectangle from a bitmap and
280 its mask into another rectangle and does a compress/stretch
281 to fit a given destination rectangle.
283 @note When using this function with a 256 Mask bitmap, it blends.
284 Otherwise (e.g. with a 4bpp mask), this function masks rather than blends.
285 If a user wants to blend the source into the destination they should use
286 CFbsBitGc::AlphaBlendBitmaps() instead.
291 @param aDestRect The rectangle within which the masked bitmap is to be drawn.
292 @param aBitmap A pointer to the source bitmap.
293 @param aSourceRect The rectangle in the source bitmap that is copied to the
294 destination rectangle.
295 @param aMaskBitmap A pointer to the mask bitmap.
296 @param aInvertMask If false, a source pixel that is masked by a black pixel
297 is not transferred to the destination rectangle. If true, then a source pixel
298 that is masked by a white pixel is not transferred to the destination rectangle.
301 @pre aBitmap->Handle() != 0
302 @pre aMaskBitmap != NULL
303 @pre aMaskBitmap->Handle() != 0
304 @pre !aSourceRect.IsEmpty()
305 @pre aSourceRect should be in the bounds of the bitmap
307 EXPORT_C void CFbsBitGc::DrawBitmapMasked(const TRect& aDestRect,
308 const CFbsBitmap* aBitmap,
309 const TRect& aSourceRect,
310 const CFbsBitmap* aMaskBitmap,
313 if (aBitmap == NULL || !aBitmap->Handle() || aMaskBitmap == NULL ||
314 !aMaskBitmap->Handle() || aSourceRect.IsEmpty() || CheckDevice(aDestRect))
319 aBitmap->BeginDataAccess();
320 aMaskBitmap->BeginDataAccess();
322 //aSourceRect should be in the bounds of the bitmap
323 TSize bitmapSize(aBitmap->SizeInPixels());
324 if ( aSourceRect.iTl.iX < 0
325 || aSourceRect.iTl.iY < 0
326 || aSourceRect.iBr.iX > bitmapSize.iWidth
327 || aSourceRect.iBr.iY > bitmapSize.iHeight)
329 aBitmap->EndDataAccess(ETrue);
330 aMaskBitmap->EndDataAccess(ETrue);
334 TRect destRect(aDestRect);
335 destRect.Move(iOrigin);
337 TRect clippedDestRect(destRect);
338 if (UserClipRect(clippedDestRect))
340 aBitmap->EndDataAccess(ETrue);
341 aMaskBitmap->EndDataAccess(ETrue);
346 const TBool opaqueSource = (!IsAlphaChannel(aBitmap->DisplayMode())) && (iDrawMode == EDrawModePEN);
347 iDevice->DrawingBegin();
349 CBitwiseBitmap* srcebmp = ((CFbsBitGcBitmap*)aBitmap)->Address();
350 CBitwiseBitmap* maskbmp = ((CFbsBitGcBitmap*)aMaskBitmap)->Address();
351 BG_ASSERT_DEBUG(srcebmp,EBitgdiPanicInvalidBitmap);
352 BG_ASSERT_DEBUG(maskbmp,EBitgdiPanicInvalidBitmap);
354 CFbsRasterizer* rasterizer = PrepareRasterizerForExtendedBitmap(*aBitmap, destRect, aSourceRect);
355 CFbsRasterizer* maskRasterizer = NULL;
356 if (srcebmp != maskbmp)
358 if (aMaskBitmap->SizeInPixels().iWidth >= aBitmap->SizeInPixels().iWidth
359 && aMaskBitmap->SizeInPixels().iHeight >= aBitmap->SizeInPixels().iHeight)
361 // Mask is not tiled. Pass same region of interest as source bitmap to rasterizer.
362 maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap, destRect, aSourceRect);
366 // Mask is tiled. Do not pass any region of interest to rasterizer.
367 maskRasterizer = PrepareRasterizerForExtendedBitmap(*aMaskBitmap);
371 const TPoint ditherOrigin(iDitherOrigin + aDestRect.iTl);
372 const TInt limit = iDefaultRegionPtr->Count();
374 CGraphicsAccelerator* ga = GraphicsAccelerator();
375 if (ga && iShadowMode==CFbsDrawDevice::ENoShadow && (aMaskBitmap->DisplayMode()!=EGray2 || !aInvertMask) && iDrawMode==EDrawModePEN)
377 TInt gaOperationResult = KErrUnknown;
378 TAcceleratedBitmapSpec bitmapSpec(const_cast<CFbsBitmap*>(aBitmap));
379 iDevice->DrawingEnd();
380 TAcceleratedBitmapSpec maskSpec(const_cast<CFbsBitmap*>(aMaskBitmap));
381 const TPoint offset(aSourceRect.iTl - destRect.iTl);
383 if (destRect.Size() == aSourceRect.Size())
385 for(TInt count=0;count<limit;count++)
387 iClipRect=(*iDefaultRegionPtr)[count];
388 if(!iClipRect.Intersects(clippedDestRect))
390 iClipRect.Intersection(clippedDestRect);
392 TRect clippedSrceRect(iClipRect);
393 clippedSrceRect.Move(offset);
395 gaOperationResult = ga->Operation(TGopBitBltMasked(iClipRect.iTl,bitmapSpec,clippedSrceRect,maskSpec));
396 if (gaOperationResult!=KErrNone)
398 iDevice->iDrawDevice->UpdateRegion(iClipRect);
403 RRegion clippedRegion;
404 for(TInt clipIt=0;clipIt<limit;clipIt++)
406 TRect clipRect((*iDefaultRegionPtr)[clipIt]);
407 clipRect.Intersection(clippedDestRect);
408 if (!clipRect.IsEmpty())
409 clippedRegion.AddRect(clipRect);
411 TRect srcCopy(aSourceRect); // Needed because TGopScaledBitBltMasked takes a non-const value
412 // const_cast needed because Operation takes a non-const region ptr :(
413 gaOperationResult = ga->Operation(TGopScaledBitBltMasked(destRect,bitmapSpec,srcCopy,maskSpec),clippedRegion.Count(),const_cast<TRect*>(clippedRegion.RectangleList()));
414 if (gaOperationResult==KErrNone)
415 iDevice->iDrawDevice->Update(clippedRegion);
416 clippedRegion.Close();
418 if (gaOperationResult==KErrNone)
420 iDevice->DrawingBegin();
424 iDrawMode = EDrawModeWriteAlpha;
425 for (TInt count = 0; count < limit; count++)
427 iClipRect = (*iDefaultRegionPtr)[count];
428 if (!iClipRect.Intersects(clippedDestRect))
430 iClipRect.Intersection(clippedDestRect);
431 DoDrawBitmapMasked(destRect,
433 aBitmap->DataAddress(),
436 aMaskBitmap->DataAddress(),
437 aInvertMask, ditherOrigin);
438 iDevice->iDrawDevice->UpdateRegion(iClipRect);
441 iDrawMode = EDrawModePEN;
442 iDevice->DrawingEnd();
446 rasterizer->EndBitmap(aBitmap->SerialNumber());
450 maskRasterizer->EndBitmap(aMaskBitmap->SerialNumber());
452 aBitmap->EndDataAccess(ETrue);
453 aMaskBitmap->EndDataAccess(ETrue);
456 /** The method draws a specified rectangle from a bitmap and
457 its mask into another rectangle and does a compress/stretch
458 to fit a given destination rectangle.
460 This is an overload, which takes CWsBitmap* as argument, which
461 in turn calls the other overload.
463 Note: A pointer to CWsBitmap must have the same pointer value as a pointer
464 to the associated CFbsBitmap, otherwise code in BitGdi component will be
467 @note When using this function with a 256 Mask bitmap, it blends.
468 Otherwise (e.g. with a 4bpp mask), this function masks rather than blends.
469 If a user wants to blend the source into the destination they should use
470 CFbsBitGc::AlphaBlendBitmaps() instead.
475 @param aDestRect The rectangle within which the masked bitmap is to be drawn.
476 @param aBitmap A pointer to the source bitmap.
477 @param aSourceRect The rectangle in the source bitmap that is copied to the
478 destination rectangle.
479 @param aMaskBitmap A pointer to the mask bitmap.
480 @param aInvertMask If false, a source pixel that is masked by a black pixel
481 is not transferred to the destination rectangle. If true, then a source pixel
482 that is masked by a white pixel is not transferred to the destination rectangle.
485 @pre aBitmap->Handle() != 0
486 @pre aMaskBitmap != NULL
487 @pre aMaskBitmap->Handle() != 0
488 @pre !aSourceRect.IsEmpty()
490 EXPORT_C void CFbsBitGc::DrawBitmapMasked(const TRect& aDestRect,
491 const CWsBitmap* aBitmap,
492 const TRect& aSourceRect,
493 const CWsBitmap* aMaskBitmap,
496 DrawBitmapMasked(aDestRect,REINTERPRET_CAST(const CFbsBitmap*,aBitmap),aSourceRect,REINTERPRET_CAST(const CFbsBitmap*,aMaskBitmap),aInvertMask);