fbs/fontandbitmapserver/trasterizer/src/examplerasterizer.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     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 	}