Update contrib.
1 // Copyright (c) 2008-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 "examplerasterizer.h"
20 /** Create a new example rasterizer.
22 @return A pointer to a newly constructed CFbsRasterizer object if successful,
23 or NULL if no memory is available.
25 EXPORT_C CFbsRasterizer* CFbsRasterizer::New()
27 return new CExampleRasterizer;
33 CExampleRasterizer::CExampleRasterizer()
34 : iRegisteredBmps(_FOFF(CRegisteredBitmap, iLink)), iRecentBmps(_FOFF(CRegisteredBitmap, iLink))
39 CExampleRasterizer::~CExampleRasterizer()
41 while (!iRegisteredBmps.IsEmpty())
43 delete iRegisteredBmps.First();
45 while (!iRecentBmps.IsEmpty())
47 delete iRecentBmps.First();
52 /** Register a bitmap with this rasterizer for rendering.
54 In this example an extended bitmap is a tricolour flag with three coloured stripes of the same size
55 being either vertically or horizontally oriented. The colours to be used in the flag and a TUint8
56 that specifies horizontal or vertical stripes are passed in the aBitmapDesc.iData parameter, which
57 should point to a buffer containing the three stripe colours first, each colour as three TUint8
58 values, followed by a TUint8 value where 1 means horizontal stripes and 0 means vertical stripes.
60 The only display modes supported by this example rasterizer are EGray256, EColor64K, EColor16MU and EColor16MAP.
62 If the rasterizer cannot allocate enough memory for rendering the extended bitmap this function
63 will return silently. If an unsupported display mode is passed this function will return silently.
65 @see CFbsRasterizer::BeginBitmap()
68 void CExampleRasterizer::BeginBitmap(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, const TRegion* aRegionOfInterest)
70 // Check that the passed extended bitmap description is valid
71 if ((aBitmapDesc.iSizeInPixels.iWidth <= 0) || (aBitmapDesc.iSizeInPixels.iHeight <= 0)
72 // This test rasterizer only supports EGray256, EColor64K, EColor16MU and EColor16MAP
73 || ((aBitmapDesc.iDispMode != EGray256) && (aBitmapDesc.iDispMode != EColor64K) && (aBitmapDesc.iDispMode != EColor16MU) && (aBitmapDesc.iDispMode != EColor16MAP))
74 || (aBitmapDesc.iDataType != KUidExampleExtendedBitmap)
75 || (aBitmapDesc.iData == NULL)
76 || (aBitmapDesc.iDataSize <= 0))
79 RDebug::Printf("Example Rasterizer Error: Invalid TBitmapDesc passed to CExampleRasterizer::BeginBitmap()");
84 // Check if the bitmap is already registered
85 CRegisteredBitmap* foundRegBmp = RegisteredBitmap(aBitmapId);
88 // Not registered: check if the bitmap is in the cache of recently used bitmaps
89 foundRegBmp = RecentBitmap(aBitmapId);
92 // Take the bitmap out of the cache and put it in the list of registered bitmaps
93 foundRegBmp->iLink.Deque();
94 iTotalRecentBmpSize -= foundRegBmp->iBufLength;
95 iRegisteredBmps.AddLast(*foundRegBmp);
101 // Make sure an extended bitmap is not registered more than once with different attributes
102 if ((foundRegBmp->iSizeInPixels != aBitmapDesc.iSizeInPixels)
103 || (foundRegBmp->iDispMode != aBitmapDesc.iDispMode)
104 || (foundRegBmp->iDataType != aBitmapDesc.iDataType))
106 RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::BeginBitmap() called for an extended bitmap that has already been registered with a different TBitmapDesc");
110 // This bitmap is already registered, just increment its reference count and return
111 foundRegBmp->iRefCount++;
115 // Get the scanline length we should use for this display mode as the scanlines we draw must be 32-bit aligned
116 TInt scanLineLength = CFbsBitmap::ScanLineLength(aBitmapDesc.iSizeInPixels.iWidth, aBitmapDesc.iDispMode);
117 // Create a CRegisteredBitmap object to save the pre-rendered bitmap
118 TInt bufLength = scanLineLength * aBitmapDesc.iSizeInPixels.iHeight;
119 // Allocate bufLength extra bytes for the embedded pixel buffer
120 CRegisteredBitmap* regBmp = new(bufLength) CRegisteredBitmap(aBitmapId, aBitmapDesc, bufLength);
124 RDebug::Printf("Example Rasterizer Error: Failed to allocate memory");
129 // Pre-render the flag that the extended bitmap represents
130 RMemReadStream readStream;
131 readStream.Open(aBitmapDesc.iData, aBitmapDesc.iDataSize);
132 TInt err = regBmp->Draw(readStream, aRegionOfInterest);
137 RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::CRegisteredBitmap::Draw() returned %d", err);
144 iRegisteredBmps.AddLast(*regBmp);
145 regBmp->iRefCount = 1;
148 /** Unregister an extended bitmap from this rasterizer.
150 @see CFbsRasterizer::EndBitmap()
153 void CExampleRasterizer::EndBitmap(TInt64 aBitmapId)
155 CRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId);
158 if (--regBmp->iRefCount == 0)
160 // Put unregistered bitmap in the cache of recently used bitmaps if wholly pre-rendered
161 // and there is an active scheduler to add the idle-time clean-up active object to
162 if (regBmp->iWhole && CActiveScheduler::Current())
166 iIdle = CIdle::New(CActive::EPriorityIdle);
173 regBmp->iLink.Deque();
174 iRecentBmps.AddFirst(*regBmp);
175 iTotalRecentBmpSize += regBmp->iBufLength;
176 // Delete the least recently used bitmaps if the maximum size of the cache is exceeded
177 while (iTotalRecentBmpSize > KMaxRecentBmpCacheSize)
179 regBmp = iRecentBmps.Last();
180 iTotalRecentBmpSize -= regBmp->iBufLength;
183 // If the cache is not empty make sure the idle-time clean-up active object is scheduled to run
184 if (!iRecentBmps.IsEmpty() && !iIdle->IsActive())
186 iIdle->Start(TCallBack(IdleFunction, this));
198 RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::EndBitmap() called for a bitmap that is not registered");
203 /** Return a scanline from the passed extended bitmap given its bitmap id.
205 @see CFbsRasterizer::ScanLine()
209 const TUint32* CExampleRasterizer::ScanLine(TInt64 aBitmapId, const TPoint& aPixel, TInt aLength)
211 // Check that BeginBitmap() was called successfully and the passed bitmap was registered
212 // with this rasterizer
213 CRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId);
217 if ((aPixel.iX < 0) || (aPixel.iX >= regBmp->iSizeInPixels.iWidth)
218 || (aPixel.iY < 0) || (aPixel.iY >= regBmp->iSizeInPixels.iHeight)
219 || (aLength > (regBmp->iSizeInPixels.iWidth - aPixel.iX))) // the requested length in pixels is greater than the declared width of the bitmap
222 RDebug::Printf("Example Rasterizer Error: Invalid parameter passed to CExampleRasterizer::ScanLine()");
227 TInt scanLineLength = CFbsBitmap::ScanLineLength(regBmp->iSizeInPixels.iWidth, regBmp->iDispMode);
228 return reinterpret_cast<TUint32*>(regBmp->Buffer() + (aPixel.iY * scanLineLength));
233 RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::ScanLine() called for a bitmap that is not registered");
240 /** Only MFbsRasterizerClearCache available, KErrExtensionNotSupported returned for all other cases.
242 @see CFbsRasterizer::GetInterface()
244 TInt CExampleRasterizer::GetInterface(TUid aInterfaceId, TAny*& aInterface)
249 switch (aInterfaceId.iUid)
251 case KUidFbsRasterizerClearCache:
252 aInterface = static_cast<MFbsRasterizerClearCache*>(this);
255 err = KErrExtensionNotSupported;
263 /** Gets a bitmap that has been registered with this rasterizer.
265 @param aBitmapId The ID of the bitmap to check for.
267 @return A pointer to the registered bitmap if found, NULL otherwise.
269 CExampleRasterizer::CRegisteredBitmap* CExampleRasterizer::RegisteredBitmap(TInt64 aBitmapId)
271 TDblQueIter<CRegisteredBitmap> iter(iRegisteredBmps);
272 while (CRegisteredBitmap* regBmp = iter++)
274 if (regBmp->iBitmapId == aBitmapId)
282 /** Gets a bitmap that has been recently used with this rasterizer.
284 @param aBitmapId The ID of the bitmap to check for.
286 @return A pointer to the recently used bitmap if found, NULL otherwise.
288 CExampleRasterizer::CRegisteredBitmap* CExampleRasterizer::RecentBitmap(TInt64 aBitmapId)
290 TDblQueIter<CRegisteredBitmap> iter(iRecentBmps);
291 while (CRegisteredBitmap* regBmp = iter++)
293 if (regBmp->iBitmapId == aBitmapId)
301 /** Releases the memory for all the recently rasterized extended bitmaps kept in the cache.
302 This function is called by the idle-time active object.
304 @param aSelf A pointer to the rasterizer object.
306 @return Zero to indicate that this function needn't be automatically called again.
308 TInt CExampleRasterizer::IdleFunction(TAny* aPtr)
310 CExampleRasterizer* self = static_cast<CExampleRasterizer*>(aPtr);
311 while (!self->iRecentBmps.IsEmpty())
313 delete self->iRecentBmps.First();
315 self->iTotalRecentBmpSize = 0;
322 CExampleRasterizer::CRegisteredBitmap::CRegisteredBitmap(TInt64 aBitmapId,
323 const TBitmapDesc& aBitmapDesc,
325 : iBitmapId(aBitmapId),
326 iSizeInPixels(aBitmapDesc.iSizeInPixels),
327 iDispMode(aBitmapDesc.iDispMode),
328 iDataType(aBitmapDesc.iDataType),
329 iBufLength(aBufLength)
334 CExampleRasterizer::CRegisteredBitmap::~CRegisteredBitmap()
339 /** Rasterize a registered extended bitmap. The results are stored into the memory buffer embedded in this object.
341 @param aReadStream A stream to read the proprietary data from.
342 @param aRegionOfInterest The region within which scanline access requests will be made, if known.
344 @return KErrNone on success, KErrNotSupported if the display mode is not supported,
345 KErrEof if there is not enough data to read, KErrArgument if aRegionOfInterest is out of bounds.
347 TInt CExampleRasterizer::CRegisteredBitmap::Draw(RMemReadStream& aReadStream, const TRegion* aRegionOfInterest)
349 if (aRegionOfInterest && !aRegionOfInterest->IsContainedBy(iSizeInPixels))
354 // Read the three flag colours and the horizontal stripe flag from the data
355 TRgb colour1, colour2, colour3;
356 TUint8 horizontalStripe;
358 aReadStream >> colour1;
359 aReadStream >> colour2;
360 aReadStream >> colour3;
361 aReadStream >> horizontalStripe;
372 c1 = colour1.Gray256();
373 c2 = colour2.Gray256();
374 c3 = colour3.Gray256();
378 c1 = colour1.Color64K();
379 c2 = colour2.Color64K();
380 c3 = colour3.Color64K();
384 c1 = colour1.Color16MU() | 0xFF000000;
385 c2 = colour2.Color16MU() | 0xFF000000;
386 c3 = colour3.Color16MU() | 0xFF000000;
390 c1 = colour1.Color16MAP();
391 c2 = colour2.Color16MAP();
392 c3 = colour3.Color16MAP();
396 return KErrNotSupported;
399 // If no region of interest is specified, rasterize the whole size of the bitmap
400 // Otherwise rasterize only the rectangles in the region of interest
401 // (Method takes no account of overlapping rectangles)
402 TRect wholeRect(iSizeInPixels);
405 if (aRegionOfInterest)
407 numRects = aRegionOfInterest->Count();
408 rects = aRegionOfInterest->RectangleList();
409 // Pre-fill the flag with white so that areas outside the region of interest are white
410 // (this is not necessary but has been added to allow use of this rasterizer in BitGDI testing)
411 Mem::Fill(Buffer(), iBufLength, 0xFF);
415 // Set the only rect to be drawn to the whole size of the bitmap as no region of interest is specified
420 // Get the scanline length we should use for this display mode as the scanlines we draw must be 32-bit aligned
421 TInt scanLineLength = CFbsBitmap::ScanLineLength(iSizeInPixels.iWidth, iDispMode);
423 if (horizontalStripe)
425 // Horizontal stripes
426 TInt stripeHeight = iSizeInPixels.iHeight / 3;
427 for (TInt r = 0; r < numRects; ++r)
429 for (TInt h = rects[r].iTl.iY; h < rects[r].iBr.iY; ++h)
431 for (TInt w = rects[r].iTl.iX; w < rects[r].iBr.iX; ++w)
433 if (h < stripeHeight)
435 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c1, bpp); // top
437 else if (h < iSizeInPixels.iHeight - stripeHeight)
439 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c2, bpp); // middle
443 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c3, bpp); // bottom
452 TInt stripeWidth = iSizeInPixels.iWidth / 3;
453 for (TInt r = 0; r < numRects; ++r)
455 for (TInt h = rects[r].iTl.iY; h < rects[r].iBr.iY; ++h)
457 for (TInt w = rects[r].iTl.iX; w < rects[r].iBr.iX; ++w)
461 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c1, bpp); // left
463 else if (w < iSizeInPixels.iWidth - stripeWidth)
465 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c2, bpp); // middle
469 Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c3, bpp); // right
476 iWhole = (numRects == 1 && rects[0] == wholeRect);
480 /** Gets a pointer to the pre-rendered buffer for this registered bitmap.
482 TUint8* CExampleRasterizer::CRegisteredBitmap::Buffer()
484 // Adding one to "this" is the same as adding sizeof(*this) to the address of this object
485 // The result points to the pre-rendered buffer, located right after the instance variables
486 return reinterpret_cast<TUint8*>(this + 1);
489 /** Implementation of MFbsRasterizerClearCache::ClearCache() to allow test code to
490 clear the cache of recently used extended bitmaps.
492 void CExampleRasterizer::ClearCache()
494 while (!iRecentBmps.IsEmpty())
496 delete iRecentBmps.First();
498 iTotalRecentBmpSize = 0;
499 if (iIdle && iIdle->IsActive())