os/graphics/fbs/fontandbitmapserver/trasterizer/src/examplerasterizer.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "examplerasterizer.h"
    17 #include <s32mem.h>
    18 #include <fbs.h>
    19 
    20 /** Create a new example rasterizer.
    21 
    22 @return A pointer to a newly constructed CFbsRasterizer object if successful,
    23 or NULL if no memory is available.
    24  */
    25 EXPORT_C CFbsRasterizer* CFbsRasterizer::New()
    26 	{
    27 	return new CExampleRasterizer;
    28 	}
    29 
    30 
    31 /** Constructor.
    32  */
    33 CExampleRasterizer::CExampleRasterizer()
    34 	: iRegisteredBmps(_FOFF(CRegisteredBitmap, iLink)), iRecentBmps(_FOFF(CRegisteredBitmap, iLink))
    35 	{}
    36 
    37 /** Destructor.
    38  */
    39 CExampleRasterizer::~CExampleRasterizer()
    40 	{
    41 	while (!iRegisteredBmps.IsEmpty())
    42 		{
    43 		delete iRegisteredBmps.First();
    44 		}
    45 	while (!iRecentBmps.IsEmpty())
    46 		{
    47 		delete iRecentBmps.First();
    48 		}
    49 	delete iIdle;
    50 	}
    51 
    52 /** Register a bitmap with this rasterizer for rendering.
    53 
    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.
    59 
    60 The only display modes supported by this example rasterizer are EGray256, EColor64K, EColor16MU and EColor16MAP.
    61 
    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.
    64 
    65 @see CFbsRasterizer::BeginBitmap()
    66 @see EndBitmap()
    67  */
    68 void CExampleRasterizer::BeginBitmap(TInt64 aBitmapId, const TBitmapDesc& aBitmapDesc, const TRegion* aRegionOfInterest)
    69 	{
    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))
    77 		{
    78 #ifdef _DEBUG
    79 		RDebug::Printf("Example Rasterizer Error: Invalid TBitmapDesc passed to CExampleRasterizer::BeginBitmap()");
    80 #endif // _DEBUG
    81 		return;
    82 		}
    83 	
    84 	// Check if the bitmap is already registered
    85 	CRegisteredBitmap* foundRegBmp = RegisteredBitmap(aBitmapId);
    86 	if (!foundRegBmp)
    87 		{
    88 		// Not registered: check if the bitmap is in the cache of recently used bitmaps
    89 		foundRegBmp = RecentBitmap(aBitmapId);
    90 		if (foundRegBmp)
    91 			{
    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);
    96 			}
    97 		}
    98 	if (foundRegBmp)
    99 		{
   100 #ifdef _DEBUG
   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))
   105 			{
   106 			RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::BeginBitmap() called for an extended bitmap that has already been registered with a different TBitmapDesc");
   107 			}
   108 #endif // _DEBUG
   109 		
   110 		// This bitmap is already registered, just increment its reference count and return
   111 		foundRegBmp->iRefCount++;
   112 		return;
   113 		}
   114 	
   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);
   121 	if (!regBmp)
   122 		{
   123 #ifdef _DEBUG
   124 		RDebug::Printf("Example Rasterizer Error: Failed to allocate memory");
   125 #endif // _DEBUG		
   126 		return;
   127 		}
   128 	
   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);
   133 	readStream.Close();
   134 	if (err != KErrNone)
   135 		{
   136 #ifdef _DEBUG
   137 		RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::CRegisteredBitmap::Draw() returned %d", err);
   138 #endif // _DEBUG
   139 		delete regBmp;
   140 		return;
   141 		}
   142 	
   143 	// Success
   144 	iRegisteredBmps.AddLast(*regBmp);
   145 	regBmp->iRefCount = 1;
   146 	}
   147 
   148 /** Unregister an extended bitmap from this rasterizer. 
   149 
   150 @see CFbsRasterizer::EndBitmap()
   151 @see BeginBitmap()
   152  */
   153 void CExampleRasterizer::EndBitmap(TInt64 aBitmapId)
   154 	{
   155 	CRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId);
   156 	if (regBmp)
   157 		{
   158 		if (--regBmp->iRefCount == 0)
   159 			{
   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())
   163 				{
   164 				if (!iIdle)
   165 					{
   166 					iIdle = CIdle::New(CActive::EPriorityIdle);
   167 					if (!iIdle)
   168 						{
   169 						delete regBmp;
   170 						return;
   171 						}
   172 					}
   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)
   178 					{
   179 					regBmp = iRecentBmps.Last();
   180 					iTotalRecentBmpSize -= regBmp->iBufLength;
   181 					delete regBmp;
   182 					}
   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())
   185 					{
   186 					iIdle->Start(TCallBack(IdleFunction, this));
   187 					}
   188 				}
   189 			else
   190 				{
   191 				delete regBmp;
   192 				}
   193 			}
   194 		}
   195 #ifdef _DEBUG
   196 	else
   197 		{
   198 		RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::EndBitmap() called for a bitmap that is not registered");
   199 		}
   200 #endif // _DEBUG
   201 	}
   202 
   203 /** Return a scanline from the passed extended bitmap given its bitmap id. 
   204 
   205 @see CFbsRasterizer::ScanLine()
   206 @see BeginBitmap()
   207 @see EndBitmap()
   208  */
   209 const TUint32* CExampleRasterizer::ScanLine(TInt64 aBitmapId, const TPoint& aPixel, TInt aLength)
   210 	{
   211 	// Check that BeginBitmap() was called successfully and the passed bitmap was registered
   212 	// with this rasterizer
   213 	CRegisteredBitmap* regBmp = RegisteredBitmap(aBitmapId);
   214 	if (regBmp)
   215 		{
   216 		// Parameter check
   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
   220 			{
   221 #ifdef _DEBUG
   222 			RDebug::Printf("Example Rasterizer Error: Invalid parameter passed to CExampleRasterizer::ScanLine()");
   223 #endif // _DEBUG
   224 			return NULL;
   225 			}
   226 		
   227 		TInt scanLineLength = CFbsBitmap::ScanLineLength(regBmp->iSizeInPixels.iWidth, regBmp->iDispMode);
   228 		return reinterpret_cast<TUint32*>(regBmp->Buffer() + (aPixel.iY * scanLineLength));
   229 		}
   230 #ifdef _DEBUG
   231 	else
   232 		{
   233 		RDebug::Printf("Example Rasterizer Error: CExampleRasterizer::ScanLine() called for a bitmap that is not registered");
   234 		}
   235 #endif // _DEBUG
   236 	
   237 	return NULL;
   238 	}
   239 
   240 /** Only MFbsRasterizerClearCache available, KErrExtensionNotSupported returned for all other cases.
   241 
   242 @see CFbsRasterizer::GetInterface()
   243  */
   244 TInt CExampleRasterizer::GetInterface(TUid aInterfaceId, TAny*& aInterface)
   245 	{
   246 	aInterface = NULL;
   247 	TInt err = KErrNone;
   248 	
   249 	switch (aInterfaceId.iUid)
   250 		{
   251 		case KUidFbsRasterizerClearCache:
   252 			aInterface = static_cast<MFbsRasterizerClearCache*>(this);
   253 			break;
   254 		default:
   255 			err = KErrExtensionNotSupported;						
   256 			break;
   257 		}
   258 	
   259 	return err;
   260 	}
   261 
   262 
   263 /** Gets a bitmap that has been registered with this rasterizer.
   264 
   265 @param aBitmapId The ID of the bitmap to check for.
   266 
   267 @return A pointer to the registered bitmap if found, NULL otherwise.
   268  */
   269 CExampleRasterizer::CRegisteredBitmap* CExampleRasterizer::RegisteredBitmap(TInt64 aBitmapId)
   270 	{
   271 	TDblQueIter<CRegisteredBitmap> iter(iRegisteredBmps);
   272 	while (CRegisteredBitmap* regBmp = iter++)
   273 		{
   274 		if (regBmp->iBitmapId == aBitmapId)
   275 			{
   276 			return regBmp;
   277 			}
   278 		}
   279 	return NULL;
   280 	}
   281 
   282 /** Gets a bitmap that has been recently used with this rasterizer.
   283 
   284 @param aBitmapId The ID of the bitmap to check for.
   285 
   286 @return A pointer to the recently used bitmap if found, NULL otherwise.
   287  */
   288 CExampleRasterizer::CRegisteredBitmap* CExampleRasterizer::RecentBitmap(TInt64 aBitmapId)
   289 	{
   290 	TDblQueIter<CRegisteredBitmap> iter(iRecentBmps);
   291 	while (CRegisteredBitmap* regBmp = iter++)
   292 		{
   293 		if (regBmp->iBitmapId == aBitmapId)
   294 			{
   295 			return regBmp;
   296 			}
   297 		}
   298 	return NULL;
   299 	}
   300 
   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.
   303 
   304 @param aSelf A pointer to the rasterizer object.
   305 
   306 @return Zero to indicate that this function needn't be automatically called again.
   307  */
   308 TInt CExampleRasterizer::IdleFunction(TAny* aPtr)
   309 	{
   310 	CExampleRasterizer* self = static_cast<CExampleRasterizer*>(aPtr);
   311 	while (!self->iRecentBmps.IsEmpty())
   312 		{
   313 		delete self->iRecentBmps.First();
   314 		}
   315 	self->iTotalRecentBmpSize = 0;
   316 	return 0;
   317 	}
   318 
   319 
   320 /** Constructor.
   321  */
   322 CExampleRasterizer::CRegisteredBitmap::CRegisteredBitmap(TInt64 aBitmapId,
   323 	                                                     const TBitmapDesc& aBitmapDesc,
   324 	                                                     TInt aBufLength)
   325 	: iBitmapId(aBitmapId),
   326 	  iSizeInPixels(aBitmapDesc.iSizeInPixels),
   327 	  iDispMode(aBitmapDesc.iDispMode),
   328 	  iDataType(aBitmapDesc.iDataType),
   329 	  iBufLength(aBufLength)
   330 	{}
   331 
   332 /** Destructor.
   333  */
   334 CExampleRasterizer::CRegisteredBitmap::~CRegisteredBitmap()
   335 	{
   336 	iLink.Deque();
   337 	}
   338 
   339 /** Rasterize a registered extended bitmap. The results are stored into the memory buffer embedded in this object.
   340 
   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.
   343 
   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.
   346  */
   347 TInt CExampleRasterizer::CRegisteredBitmap::Draw(RMemReadStream& aReadStream, const TRegion* aRegionOfInterest)
   348 	{
   349 	if (aRegionOfInterest && !aRegionOfInterest->IsContainedBy(iSizeInPixels))
   350 		{
   351 		return KErrArgument;
   352 		}
   353 	
   354 	// Read the three flag colours and the horizontal stripe flag from the data
   355 	TRgb colour1, colour2, colour3;
   356 	TUint8 horizontalStripe;
   357 	TRAPD(err,
   358 		aReadStream >> colour1;
   359 		aReadStream >> colour2;
   360 		aReadStream >> colour3;
   361 		aReadStream >> horizontalStripe;
   362 		);
   363 	if (err != KErrNone)
   364 		{
   365 		return err;
   366 		}
   367 	TUint32 c1, c2, c3;
   368 	TInt bpp;
   369 	switch (iDispMode)
   370 		{
   371 	case EGray256:
   372 		c1 = colour1.Gray256();
   373 		c2 = colour2.Gray256();
   374 		c3 = colour3.Gray256();
   375 		bpp = 1;
   376 		break;
   377 	case EColor64K:
   378 		c1 = colour1.Color64K();
   379 		c2 = colour2.Color64K();
   380 		c3 = colour3.Color64K();
   381 		bpp = 2;
   382 		break;
   383 	case EColor16MU:
   384 		c1 = colour1.Color16MU() | 0xFF000000;
   385 		c2 = colour2.Color16MU() | 0xFF000000;
   386 		c3 = colour3.Color16MU() | 0xFF000000;
   387 		bpp = 4;
   388 		break;
   389 	case EColor16MAP:
   390 		c1 = colour1.Color16MAP();
   391 		c2 = colour2.Color16MAP();
   392 		c3 = colour3.Color16MAP();
   393 		bpp = 4;
   394 		break;
   395 	default:
   396 		return KErrNotSupported;
   397 		}
   398 	
   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);
   403 	TInt numRects;
   404 	const TRect* rects;
   405 	if (aRegionOfInterest)
   406 		{
   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);
   412 		}
   413 	else
   414 		{
   415 		// Set the only rect to be drawn to the whole size of the bitmap as no region of interest is specified
   416 		numRects = 1;
   417 		rects = &wholeRect;
   418 		}
   419 	
   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);
   422 	
   423 	if (horizontalStripe)
   424 		{
   425 		// Horizontal stripes
   426 		TInt stripeHeight = iSizeInPixels.iHeight / 3;
   427 		for (TInt r = 0; r < numRects; ++r)
   428 			{
   429 			for (TInt h = rects[r].iTl.iY; h < rects[r].iBr.iY; ++h)
   430 				{
   431 				for (TInt w = rects[r].iTl.iX; w < rects[r].iBr.iX; ++w)
   432 					{
   433 					if (h < stripeHeight)
   434 						{
   435 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c1, bpp); // top
   436 						}
   437 					else if (h < iSizeInPixels.iHeight - stripeHeight)
   438 						{
   439 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c2, bpp); // middle
   440 						}
   441 					else
   442 						{
   443 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c3, bpp); // bottom
   444 						}
   445 					}
   446 				}
   447 			}
   448 		}
   449 	else
   450 		{
   451 		// Vertical stripes
   452 		TInt stripeWidth = iSizeInPixels.iWidth / 3;
   453 		for (TInt r = 0; r < numRects; ++r)
   454 			{
   455 			for (TInt h = rects[r].iTl.iY; h < rects[r].iBr.iY; ++h)
   456 				{
   457 				for (TInt w = rects[r].iTl.iX; w < rects[r].iBr.iX; ++w)
   458 					{
   459 					if (w < stripeWidth)
   460 						{
   461 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c1, bpp); // left
   462 						}
   463 					else if (w < iSizeInPixels.iWidth - stripeWidth)
   464 						{
   465 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c2, bpp); // middle
   466 						}
   467 					else
   468 						{
   469 						Mem::Copy(Buffer() + (w * bpp) + (h * scanLineLength), &c3, bpp); // right
   470 						}
   471 					}
   472 				}
   473 			}
   474 		}
   475 	
   476 	iWhole = (numRects == 1 && rects[0] == wholeRect);
   477 	return KErrNone;
   478 	}
   479 
   480 /** Gets a pointer to the pre-rendered buffer for this registered bitmap.
   481  */
   482 TUint8* CExampleRasterizer::CRegisteredBitmap::Buffer()
   483 	{
   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);
   487 	}
   488 
   489 /** Implementation of MFbsRasterizerClearCache::ClearCache() to allow test code to 
   490 clear the cache of recently used extended bitmaps.
   491  */
   492 void CExampleRasterizer::ClearCache()
   493 	{
   494 	while (!iRecentBmps.IsEmpty())
   495 		{
   496 		delete iRecentBmps.First();
   497 		}
   498 	iTotalRecentBmpSize = 0;
   499 	if (iIdle && iIdle->IsActive())
   500 		{
   501 		iIdle->Cancel();
   502 		}
   503 	}