os/graphics/graphicsdeviceinterface/directgdiadaptation/hwsrc/glyphimagecache.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "glyphimagecache.h"
    17 #include "glyphlutab.h"
    18 #include "vgengine.h"
    19 #include <fbs.h>
    20 
    21 //the image of the following size will be pre-allocated for low memory conditions.
    22 const TSize KMaxSizeImageOOM(72, 64);
    23 #ifdef DRAWGLYPH_MULTIPLY_MODE
    24 // Matrix used for converting glyphs with a background colour of black and a character colour
    25 // of white to have a background colour that is fully transparent black and a character colour
    26 // of opaque black. 
    27 const VGfloat KColorMatrix[20] = { 0, 0, 0, 1, // sets alpha of destination to R value of source
    28 				                   0, 0, 0, 0,
    29 				                   0, 0, 0, 0,
    30 				                   0, 0, 0, 0,
    31 				                   1, 1, 1, 0}; // sets RGB of destination to 1
    32 #endif // DRAWGLYPH_MULTIPLY_MODE
    33 
    34 //--------------class CFontGlyphTree --------------------
    35 /**
    36 Creates a new instance of the class. Will not be shared across different threads 
    37 
    38 @param 	aFontId The unique font identifier.
    39 @param 	aGlyphType The type for the format of a glyph bitmap.
    40 @return The pointer to the CFontGlyphTree class instance.
    41  */
    42 CFontGlyphTree* CFontGlyphTree::NewL(TUint32 aFontId, TGlyphBitmapType aGlyphType)
    43 	{
    44 	CFontGlyphTree*  self = new (ELeave) CFontGlyphTree(aFontId, aGlyphType);
    45 	CleanupStack::PushL(self);
    46 	self->ConstructL();
    47 	CleanupStack::Pop(self);
    48 	return self;
    49 	}
    50 	
    51 /**
    52 Constructor for the image font glyph tree
    53 
    54 @param 	aFontId The unique font identifier.
    55 @param 	aGlyphType The type for the format of a glyph bitmap.
    56 */
    57 CFontGlyphTree::CFontGlyphTree(TUint32 aFontId, TGlyphBitmapType aGlyphType) :
    58 	iKey(_FOFF(TGlyphEntry,iGlyphCode),ECmpTUint32),
    59 	iFontId(aFontId),
    60 	iGlyphType(aGlyphType)
    61 	{
    62 	}
    63 	
    64 /**
    65 Destructor for the image font glyph tree.
    66 
    67 Destroys the VGImages, page pool and binary tree. 
    68 */
    69 CFontGlyphTree::~CFontGlyphTree()
    70 	{
    71 	TRAP_IGNORE(DestroyAllVGImagesL());
    72 	delete iGlyphTree;
    73 	delete iPagePool;
    74 	}
    75 	
    76 /**
    77 Constructs memory page pool and binary tree. Glyph code will be used as a key.
    78 */
    79 void CFontGlyphTree::ConstructL()
    80 	{
    81 	iPagePool = CMemPagePool::NewL();
    82 	
    83 	switch(iGlyphType)
    84 		{
    85 	case EFourColourBlendGlyphBitmap:
    86 		iGlyphTree = new (ELeave) TBtreeFix<TGlyphEntryCompound, TChar> (EBtreeFast);
    87 		((TBtreeFix<TGlyphEntryCompound, TChar> *)iGlyphTree) -> Connect(iPagePool, &iKey);
    88 		break;
    89 	case EMonochromeGlyphBitmap:
    90 	case EAntiAliasedGlyphBitmap:
    91 		iGlyphTree = new (ELeave) TBtreeFix<TGlyphEntry, TChar> (EBtreeFast);
    92 		((TBtreeFix<TGlyphEntry, TChar> *)iGlyphTree) -> Connect(iPagePool, &iKey);
    93 		break;
    94 	default:
    95 		User::Leave(KErrNotSupported);
    96 		break;	
    97 		}
    98 	}
    99 	
   100 /**
   101 Searches for the image entry in the binary tree. If fails, it will create a new entry.
   102 
   103 @param	aGlyphCode General Unicode character value.
   104 @param	aGlyphImage Glyph image	bitmap data. The data structure depends on glyph type.
   105 @param	aGlyphImageSize Size of the glyph image.		
   106 @param	aEntry Binary tree entry, which comprises OpenVG image(s).
   107 @param	aDataForeground Pre-allocated buffer, which will be used for setting text VG image.
   108 
   109 @see TGlyphEntryCompound
   110 @see TGlyphEntry
   111 
   112 @pre 	Rendering engine has been constructed.
   113 @post 	Requested  OpenVG images are ready for rendering.
   114 @return KErrNone if successful;  
   115 		KErrNotSupported if font type is not supported,  
   116 		otherwise one of the other system-wide error codes.
   117 */
   118 template <class K>
   119 void CFontGlyphTree::GlyphImageEntryL(TChar aGlyphCode, const TUint8* aGlyphImage, const TSize& aGlyphImageSize, K& aEntry, TUint8* aDataForeground)
   120 	{
   121 	TBtreePos pos;
   122 	TBool found = EFalse;
   123 	found = ((TBtreeFix<K, TChar> *)iGlyphTree) -> FindL(pos, aGlyphCode);
   124 	
   125 	if(found)
   126 		{
   127 		((TBtreeFix<K, TChar> *)iGlyphTree) -> ExtractAtL(pos, aEntry);
   128 		}
   129 	else
   130 		{
   131 		aEntry.iGlyphCode = aGlyphCode;
   132 		aEntry.iForeground = VG_INVALID_HANDLE;
   133 		TInt glyphSizeInByte = 0;
   134 		
   135 		switch(iGlyphType)
   136 			{
   137 		case EFourColourBlendGlyphBitmap:
   138 			{
   139 			((TGlyphEntryCompound&) aEntry).iOutline = VG_INVALID_HANDLE;
   140 			((TGlyphEntryCompound&) aEntry).iShadow = VG_INVALID_HANDLE;
   141 			CreateVGImageL(aGlyphImage, aGlyphImageSize, aEntry.iForeground, ((TGlyphEntryCompound&) aEntry).iOutline, ((TGlyphEntryCompound&) aEntry).iShadow, NULL, NULL, NULL);
   142 			glyphSizeInByte = aGlyphImageSize.iWidth * aGlyphImageSize.iHeight;
   143 			glyphSizeInByte *= 3; //foreground, shadow, outline
   144 			break;
   145 			}
   146 		case EMonochromeGlyphBitmap:
   147 			CreateVGImageL(aGlyphImage, aGlyphImageSize, EGray2, aEntry.iForeground, aDataForeground);
   148 			glyphSizeInByte = (((aGlyphImageSize.iWidth + 31) / 32) << 2) * aGlyphImageSize.iHeight;
   149 			break;
   150 		case EAntiAliasedGlyphBitmap:
   151 			CreateVGImageL(aGlyphImage, aGlyphImageSize, EGray256, aEntry.iForeground, NULL);
   152 			glyphSizeInByte = aGlyphImageSize.iWidth * aGlyphImageSize.iHeight;
   153 			break;
   154 		default:
   155 			User::Leave(KErrNotSupported);
   156 			}
   157 
   158 		((TBtreeFix<K, TChar> *)iGlyphTree) -> InsertL(pos, aEntry);
   159 		iCacheSize += glyphSizeInByte;	
   160 		}
   161 	}
   162 
   163 /**
   164 Overridden function, which creates Open VG images for foreground, background, shadow and outline components of the font.
   165  
   166 @param 	aGlyphImage Source bitmap data in 256 grey format. Each pixel value is an index to a constant lookup table. 
   167 			Four entries of this table represent % of Outline, Shadow, Fill and Background colour to be used to get the final colour to be displayed on screen.
   168 @param	aGlyphImageSize Size of the glyph bitmap image.
   169 @param	aForeground Foreground component of the glyph.
   170 @param	aOutline	Outline component of the glyph.
   171 @param	aShadow 	Shadow component of the glyph. 
   172 @param	aPreAllocForeground Pre-allocated buffer which will be used for setting text foreground VG image
   173 @param	aPreAllocOutline Pre-allocated buffer which will be used for setting text outline VG image
   174 @param	aPreAllocShadow Pre-allocated buffer which will be used for setting text shadow VG image
   175 
   176 @post 	Requested OpenVG images are ready for rendering. 
   177 */
   178 void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, VGImage& aForeground, VGImage& aOutline, VGImage& aShadow, TUint8* aPreAllocForeground, TUint8* aPreAllocOutline, TUint8* aPreAllocShadow)
   179 	{
   180 	TInt dataStride = aGlyphImageSize.iWidth;
   181 	TInt targetByteCount = dataStride * aGlyphImageSize.iHeight;
   182 		// Allocate memory and transform source into target format.
   183 		//
   184 	TAny* foregroundBuffer = NULL;
   185 	TAny* outlineBuffer = NULL;
   186 	TAny* shadowBuffer = NULL;
   187 	TBool destroyTempBuffer = EFalse;
   188 	
   189 	if(aPreAllocForeground && aPreAllocOutline && aPreAllocShadow && 
   190 			(aGlyphImageSize.iWidth <= KMaxSizeImageOOM.iWidth) && 
   191 			(aGlyphImageSize.iHeight <= KMaxSizeImageOOM.iHeight))
   192 		{
   193 		foregroundBuffer = aPreAllocForeground;
   194 		outlineBuffer = aPreAllocOutline;
   195 		shadowBuffer = aPreAllocShadow;
   196 		}
   197 	else
   198 		{
   199 		foregroundBuffer = User::AllocL(targetByteCount);
   200 		CleanupStack::PushL(foregroundBuffer);
   201 		outlineBuffer = User::AllocL(targetByteCount);
   202 		CleanupStack::PushL(outlineBuffer);
   203 		shadowBuffer = User::AllocL(targetByteCount);
   204 		CleanupStack::PushL(shadowBuffer);
   205 		destroyTempBuffer = ETrue;
   206 		}	
   207 
   208 	TUint8* foregroundByte = static_cast <TUint8*> (foregroundBuffer); 
   209 	TUint8* outlineByte = static_cast <TUint8*> (outlineBuffer);
   210 	TUint8* shadowByte = static_cast <TUint8*> (shadowBuffer);
   211 				
   212 	const TUint8* endByte = (TUint8*)aGlyphImage + targetByteCount;
   213 	TUint8* curSrcGlyphImage = const_cast <TUint8*> (aGlyphImage);
   214 	
   215 	while (curSrcGlyphImage < endByte)
   216 		{
   217 		*outlineByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KOutlineColorIndex];
   218 		*shadowByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KShadowColorIndex];
   219 		*foregroundByte++ = FourColorBlendLookup[*curSrcGlyphImage] [KFillColorIndex];
   220 		curSrcGlyphImage++;
   221 		}
   222 
   223 	const VGImageFormat imageFormat = VG_sL_8;
   224 	if(aForeground == VG_INVALID_HANDLE)
   225 		{
   226 		aForeground = vgCreateImage(imageFormat,
   227 	                              aGlyphImageSize.iWidth, 
   228 	                              aGlyphImageSize.iHeight,
   229 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
   230 		if(aForeground == VG_INVALID_HANDLE)
   231 			{
   232 			User::Leave(KErrNoMemory);
   233 			}
   234 		aOutline = vgCreateImage(imageFormat,
   235 	                              aGlyphImageSize.iWidth, 
   236 	                              aGlyphImageSize.iHeight,
   237 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
   238 		if(aOutline == VG_INVALID_HANDLE)
   239 			{
   240 			DestroyVGImage(&aForeground);
   241 			User::Leave(KErrNoMemory);
   242 			}
   243 
   244 		aShadow = vgCreateImage(imageFormat,
   245 	                              aGlyphImageSize.iWidth, 
   246 	                              aGlyphImageSize.iHeight,
   247 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
   248 		if(aShadow == VG_INVALID_HANDLE)
   249 			{
   250 			DestroyVGImage(&aForeground, &aOutline);
   251 			User::Leave(KErrNoMemory);	
   252 			}
   253 		}
   254 	
   255 	vgImageSubData(
   256 		aForeground, foregroundBuffer, 
   257 		dataStride,	imageFormat, 
   258 		0, 0,aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
   259 	
   260 #ifdef DRAWGLYPH_MULTIPLY_MODE
   261 		VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
   262 		vgColorMatrix(image, aForeground, KColorMatrix);
   263 		vgDestroyImage(aForeground);
   264 		aForeground = image;
   265 #endif // DRAWGLYPH_MULTIPLY_MODE
   266 		
   267 	vgImageSubData(
   268 		aOutline, outlineBuffer, 
   269 		dataStride,	imageFormat, 
   270 		0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
   271 	
   272 #ifdef DRAWGLYPH_MULTIPLY_MODE
   273 		image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
   274 		vgColorMatrix(image, aOutline, KColorMatrix);
   275 		vgDestroyImage(aOutline);
   276 		aOutline = image;
   277 #endif // DRAWGLYPH_MULTIPLY_MODE
   278 		
   279 	vgImageSubData(
   280 		aShadow, shadowBuffer, 
   281 		dataStride,	imageFormat, 
   282 		0, 0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
   283 	
   284 #ifdef DRAWGLYPH_MULTIPLY_MODE
   285 		image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
   286 		vgColorMatrix(image, aShadow, KColorMatrix);
   287 		vgDestroyImage(aShadow);
   288 		aShadow = image;
   289 #endif // DRAWGLYPH_MULTIPLY_MODE	
   290 	
   291 	if(destroyTempBuffer)
   292 		{
   293 		CleanupStack::PopAndDestroy(3, foregroundBuffer);
   294 		}
   295 	}
   296 
   297 /**
   298 Overridden function, which creates OpenVG images for monochrome and anti-aliased fonts.
   299  
   300 @param 	aGlyphImage Data source bitmap in 256 or 2 Grey format. 
   301 @param 	aGlyphImageSize Glyph image data size.
   302 @param 	aDisplayMode Image display mode.
   303 @param	aForeground Foreground component of the glyph.
   304 @param	aPreAllocForeground Pre-allocated buffer which will be used for setting foreground VG image
   305 
   306 @post 	Requested OpenVG image is ready for rendering. 
   307 
   308 @panic 	Panic if bitmap display mode is not 256 grey or 2 grey.
   309 */
   310 void CFontGlyphTree::CreateVGImageL(const TUint8* aGlyphImage, const TSize& aGlyphImageSize, TDisplayMode aDisplayMode, VGImage& aForeground, TUint8* aPreAllocForeground)
   311 	{
   312 	GRAPHICS_ASSERT_DEBUG((aDisplayMode == EGray256) || (aDisplayMode == EGray2), EDirectGdiPanicInvalidDisplayMode);
   313 	GRAPHICS_ASSERT_DEBUG(aGlyphImage, EDirectGdiPanicInvalidParameter);
   314 	
   315 	VGImageFormat imageFormat = VG_IMAGE_FORMAT_INVALID;
   316 	TInt  vgCompatibleSourceStride = 0x00;
   317 	TUint32 binaryDataArray[32];
   318 	TUint8* binaryData = NULL;
   319 	TUint8* tempBuffer = NULL;	
   320 	
   321 	if(aDisplayMode == EGray256)
   322 		{
   323 		imageFormat = VG_sL_8;
   324 		vgCompatibleSourceStride = aGlyphImageSize.iWidth; 
   325 		binaryData = const_cast <TUint8*> (aGlyphImage);
   326 		}
   327 	else //EGray2
   328 		{
   329 		imageFormat = VG_BW_1;
   330 		vgCompatibleSourceStride = ((aGlyphImageSize.iWidth + 31) / 32) << 2;
   331 		if (aGlyphImageSize.iWidth > 30 || aGlyphImageSize.iHeight > 32)
   332 			{
   333 			binaryData = aPreAllocForeground;
   334 			if(!binaryData)
   335 				{
   336 				tempBuffer = (TUint8*) User::AllocL(vgCompatibleSourceStride * aGlyphImageSize.iHeight);
   337 				CleanupStack::PushL(tempBuffer);
   338 				binaryData = tempBuffer;
   339 				}
   340 			DecodeBinaryDataExLarge(aGlyphImageSize, aGlyphImage, vgCompatibleSourceStride, reinterpret_cast <TUint32*> (binaryData));
   341 			}
   342 		else
   343 			{
   344 			DecodeBinaryData(aGlyphImageSize, aGlyphImage, binaryDataArray);
   345 			binaryData = reinterpret_cast <TUint8*> (binaryDataArray);		
   346 			}
   347 		}
   348 
   349 	if(aForeground == VG_INVALID_HANDLE)
   350 		{
   351 		aForeground = vgCreateImage(imageFormat,
   352                               aGlyphImageSize.iWidth, 
   353                               aGlyphImageSize.iHeight,
   354                               VG_IMAGE_QUALITY_NONANTIALIASED);
   355 		}
   356 	
   357 	if (aForeground != VG_INVALID_HANDLE)
   358 		{
   359 			// Copy from the source image to our new VGImage
   360 		vgImageSubData(aForeground, binaryData, vgCompatibleSourceStride,	imageFormat, 
   361 			0,	0, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight);
   362 		
   363 #ifdef DRAWGLYPH_MULTIPLY_MODE
   364 		VGImage image = vgCreateImage(VG_sARGB_8888_PRE, aGlyphImageSize.iWidth, aGlyphImageSize.iHeight, VG_IMAGE_QUALITY_NONANTIALIASED);		
   365 		vgColorMatrix(image, aForeground, KColorMatrix);
   366 		vgDestroyImage(aForeground);
   367 		aForeground = image;
   368 #endif
   369 		}
   370 	else
   371 		{
   372 		if(tempBuffer)
   373 			{
   374 			CleanupStack::PopAndDestroy(tempBuffer);	
   375 			}
   376 		User::Leave(KErrNoMemory);
   377 		}
   378 		
   379 	if(tempBuffer)
   380 		{
   381 		CleanupStack::PopAndDestroy(tempBuffer);	
   382 		}
   383 	}
   384 
   385 /**
   386 Decodes binary data for monochrome bitmap.
   387 
   388 @param aDataSize Image size.
   389 @param aData Pointer to a source buffer.
   390 @param aBinaryData Pointer to a destination buffer.
   391 */
   392 void CFontGlyphTree::DecodeBinaryData(const TSize& aDataSize,
   393 								const TUint8* aData,
   394 								TUint32* aBinaryData) 
   395 	{
   396 	//Divert if the character is larger than expected; the criterion
   397 	//for choosing this function is only a heuristic, because it's perfectly legal for
   398 	//a character's bitmap to be wider than its escapement.
   399 	//
   400 	//Use a dummy value (0) for semi-ascent because this character is not italic and so semi-ascent
   401 	//is irrelevant; it's used for pseudo-italic slanting.
   402 	
   403 	TInt dataheight = aDataSize.iHeight;
   404 	TInt datalength = aDataSize.iWidth;
   405 	
   406 	TInt bitindex=0;
   407 	TInt16 repeatcount=0;
   408 	TUint32* binarydataptr=aBinaryData;
   409 	TUint32* binarydataptrlimit;
   410 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   411 		{
   412 		repeatcount=Load16(aData+(bitindex>>3));
   413 		repeatcount>>=bitindex&7;
   414 		TInt multilineflag=repeatcount&1;
   415 		repeatcount>>=1;
   416 		repeatcount&=0xf;
   417 		bitindex+=5;
   418 		binarydataptrlimit=aBinaryData+charline+repeatcount;
   419 		if(multilineflag)
   420 			{
   421 			while(binarydataptr<binarydataptrlimit)
   422 				{
   423 				TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
   424 				TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
   425 				TInt bitshift=bitindex&7;
   426 				bitshift+=(chardataoffsetptr&3)<<3;
   427 				*binarydataptr=(*chardataword++)>>bitshift;
   428 				if(bitshift) *binarydataptr|=(*chardataword<<(32-bitshift));
   429 				bitindex+=datalength;
   430 				binarydataptr++;
   431 				}
   432 			}
   433 		else
   434 			{
   435 			TInt chardataoffsetptr=TInt(aData)+(bitindex>>3);
   436 			TUint32* chardataword=(TUint32*)(chardataoffsetptr&~3);
   437 			TInt bitshift=bitindex&7;
   438 			bitshift+=(chardataoffsetptr&3)<<3;
   439 			TUint32 data=(*chardataword++)>>bitshift;
   440 			if(bitshift) data|=(*chardataword<<(32-bitshift));
   441 			while(binarydataptr<binarydataptrlimit)
   442 				*binarydataptr++=data;
   443 			bitindex+=datalength;
   444 			}
   445 		}
   446 	}
   447 	
   448 /**
   449 Decodes binary data for extra large monochrome bitmap.
   450 
   451 @param aDataSize Image size.
   452 @param aData Pointer to a source buffer.
   453 @param aStride Image data stride.
   454 @param aBinaryData Pointer to a destination buffer.
   455 */
   456 void CFontGlyphTree::DecodeBinaryDataExLarge(const TSize& aDataSize, const TUint8* aData, TInt aStride,
   457 											TUint32* aBinaryData)
   458 	{
   459 	const TInt datalength = aDataSize.iWidth;
   460 	const TInt dataheight = aDataSize.iHeight;
   461 	TInt bitindex=0;
   462 	TInt16 repeatcount=0;
   463 	TUint32* slbuffer=aBinaryData;
   464 	const TInt slwords=aStride;
   465 
   466 	for(TInt charline=0;charline<dataheight;charline+=repeatcount) // for lines in the character...
   467 		{
   468 		repeatcount=Load16(aData+(bitindex>>3));
   469 		repeatcount>>=bitindex&7;
   470 		const TInt multilineflag=repeatcount&1;
   471 		repeatcount>>=1;
   472 		repeatcount&=0xf;
   473 		bitindex+=5;
   474 		if(multilineflag)
   475 			{
   476 			for(TInt currentline=0;currentline<repeatcount;currentline++)
   477 				{
   478 				CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, 1);
   479 				bitindex+=datalength;
   480 				}
   481 			}
   482 		else
   483 			{
   484 			CopyCharLine(slbuffer,slwords,aData+(bitindex>>3),bitindex&7,datalength, repeatcount);
   485 			bitindex+=datalength;
   486 			}
   487 		}
   488 	}
   489 
   490 /**
   491 Copies image data line(s) to a destination.
   492 
   493 @param aBinaryDataPtr pointer to a destination buffer.
   494 @param aBufferWords Stride of the image.
   495 @param aData Pointer to a source buffer.
   496 @param aBitShift Number of bits, binary data will be shifted. 
   497 @param aCharWidth Width of the image.
   498 @param aRepeatCount Number of lines to copy.
   499 
   500 @panic DGDIAdapter 1018, if a null binary data pointer is passed in.
   501 */
   502 void CFontGlyphTree::CopyCharLine(TUint32*& aBinaryDataPtr,TInt aBufferWords,const TUint8* aData,TInt aBitShift,TInt aCharWidth, TInt16 aRepeatCount)
   503 	{
   504 	GRAPHICS_ASSERT_DEBUG(aBinaryDataPtr, EDirectGdiPanicInvalidPointer);//this shouldn't happen, as we always allocate memory prior to call this function 
   505 	aBitShift&=7;
   506 	TInt wordstocopy=(aCharWidth+31)>>5;
   507 	if(wordstocopy>aBufferWords) wordstocopy=aBufferWords;
   508 	TUint32* ptrlimit=aBinaryDataPtr+wordstocopy;
   509 	TUint32* dataword=(TUint32*)(TInt(aData)&~3);
   510 	aBitShift+=(TInt(aData)-TInt(dataword))<<3;
   511 	
   512 	TUint32* startBinaryDataPtr = aBinaryDataPtr;
   513 	while(aBinaryDataPtr<ptrlimit)
   514 		{
   515 		*aBinaryDataPtr=*dataword++;
   516 		*aBinaryDataPtr>>=aBitShift;
   517 		if(aBitShift) *aBinaryDataPtr|=(*dataword<<(32-aBitShift));
   518 		aBinaryDataPtr++;
   519 		}
   520 	
   521 	TUint32* curStartBinaryDataPtr = aBinaryDataPtr;
   522 	TInt byteToCopy = wordstocopy << 2;
   523 	while(aRepeatCount > 1)
   524 		{
   525 		Mem::Copy(curStartBinaryDataPtr, startBinaryDataPtr, byteToCopy);
   526 		curStartBinaryDataPtr += wordstocopy;
   527 		
   528 		aRepeatCount--;
   529 		}
   530 	aBinaryDataPtr = curStartBinaryDataPtr;
   531 	}
   532 
   533 /**
   534 Destroys OpenVG images and set variables to NULL
   535 
   536 @param aForeground Pointer to the foreground VGImage.
   537 @param aOutline Pointer to the outline VGImage.
   538 @param aShadow Pointer to the shadow VGImage.
   539 */
   540 void CFontGlyphTree::DestroyVGImage(VGImage* aForeground, VGImage* aOutline, VGImage* aShadow)
   541 	{
   542 	if(aForeground && *aForeground)
   543 		{
   544 		vgDestroyImage(*aForeground);
   545 		*aForeground = VG_INVALID_HANDLE;
   546 		}
   547 	if(aOutline && *aOutline)
   548 		{
   549 		vgDestroyImage(*aOutline);
   550 		*aOutline = VG_INVALID_HANDLE;
   551 		}
   552 	if(aShadow && *aShadow)
   553 		{
   554 		vgDestroyImage(*aShadow);
   555 		*aShadow = VG_INVALID_HANDLE;
   556 		}
   557 	}
   558 
   559 /**
   560 Goes through all entries and deletes VG images.
   561 */
   562 void CFontGlyphTree::DestroyAllVGImagesL()
   563 	{
   564 	if(iGlyphTree)
   565 		{
   566 		TBool isEntry = EFalse;
   567 		TBtreePos pos;
   568 		isEntry = iGlyphTree -> FirstL(pos);
   569 		//go through all entries and delete VG images
   570 		while (isEntry)
   571 			{
   572 			TGlyphEntry entry;
   573 			TGlyphEntryCompound entryC;
   574 			(iGlyphType == EFourColourBlendGlyphBitmap) ?
   575 					((TBtreeFix<TGlyphEntryCompound, TChar> *) iGlyphTree) -> ExtractAtL(pos, entryC) :
   576 					((TBtreeFix<TGlyphEntry, TChar> *) iGlyphTree) -> ExtractAtL(pos, entry);
   577 			
   578 			if(iGlyphType == EFourColourBlendGlyphBitmap)
   579 				{
   580 				DestroyVGImage(&entryC.iForeground, &entryC.iOutline, &entryC.iShadow);
   581 				}
   582 			else
   583 				{
   584 				DestroyVGImage(&entry.iForeground);
   585 				}	
   586 			isEntry = iGlyphTree -> NextL(pos);
   587 			}
   588 		iCacheSize = 0;
   589 		iGlyphTree -> ClearL();
   590 		}
   591 	}
   592 	
   593 /**
   594 Allows OpenVG images to be created in OOM conditions. Images will not be added to the binary tree. 
   595 */
   596 template <class K>
   597 void CFontGlyphTree::GlyphImageEntryOOML(TGlyphBitmapType aGlyphType, const TUint8* aGlyphImage, const TSize& aGlyphImageSize, K& aEntry, TUint8* aData, TUint8* aDataOutline, TUint8* aDataShadow)
   598 	{
   599 	switch(aGlyphType)
   600 		{
   601 	case EFourColourBlendGlyphBitmap:
   602 		{
   603 		CreateVGImageL(aGlyphImage, aGlyphImageSize, aEntry.iForeground, ((TGlyphEntryCompound&) aEntry).iOutline, ((TGlyphEntryCompound&) aEntry).iShadow, aData, aDataOutline, aDataShadow);
   604 		break;
   605 		}
   606 	case EMonochromeGlyphBitmap:
   607 		CreateVGImageL(aGlyphImage, aGlyphImageSize, EGray2, aEntry.iForeground, aData);
   608 		break;
   609 	case EAntiAliasedGlyphBitmap:
   610 		CreateVGImageL(aGlyphImage, aGlyphImageSize, EGray256, aEntry.iForeground, aData);
   611 		break;
   612 	default:
   613 		User::Leave(KErrNotSupported);
   614 		}
   615 	}
   616 	
   617 //--------------class CFontGlyphImageStorage --------------------
   618 /**
   619 Constructor for the font glyph image storage.
   620 
   621 @param aMaxCacheSize The maximum cache size in bytes. If storage exceeds this value, the least usable binary tree will be destroyed.
   622 */
   623 CFontGlyphImageStorage::CFontGlyphImageStorage(TInt aMaxCacheSize) :
   624 						iFontTreeList(128),
   625 						iMaxCacheSize(aMaxCacheSize)
   626 	{
   627 	}
   628 
   629 /**
   630 Destructor for the font glyph image storage.
   631 
   632 Removes and destroys all binary tree's entries in the list.
   633 */
   634 CFontGlyphImageStorage::~CFontGlyphImageStorage()
   635 	{
   636 	CleanGlyphImageCache();
   637 	DeletePreAllocatedImages();
   638 	}
   639 
   640 /**
   641 The function will free memory by deleting the least usable font tree, if the size of the cache exceeds 
   642 some pre-defined value. 
   643 
   644 @see MFontGlyphImageStorage
   645 @panic DGDIAdapter 46, if there is an inconsistency in the internal glyph cache structure.
   646 */
   647 void CFontGlyphImageStorage::CleanCacheIfRequired()
   648 	{
   649 	if(iCacheSize > iMaxCacheSize)
   650 		{
   651 		if(iFontTreeList.Count() == 1)//if it is only one tree, just delete all images
   652 			{
   653 			TInt aOldTreeSize = iFontTreeList[0]->CacheSize();
   654 			TRAP_IGNORE(iFontTreeList[0]->DestroyAllVGImagesL());
   655 			GRAPHICS_ASSERT_DEBUG(0 == (iCacheSize - (aOldTreeSize - iFontTreeList[0]->CacheSize())), EDirectGdiPanicGlyphCacheDataInconsistent);
   656 			iCacheSize = 0;
   657 			}
   658 		else
   659 			{
   660 			CFontGlyphTree* fontTree = iFontTreeList[iFontTreeList.Count() - 1];
   661 			iFontTreeList.Remove(iFontTreeList.Count() - 1);
   662 			GRAPHICS_ASSERT_DEBUG(iCacheSize >= fontTree->CacheSize(), EDirectGdiPanicGlyphCacheDataInconsistent);
   663 			iCacheSize -= fontTree->CacheSize(); //since we removed the tree, we must update overall cache size to reflect this fact
   664 			delete fontTree;
   665 			}	
   666 		}
   667 	}
   668 
   669 /**
   670 Removes all glyph trees from the storage. 
   671 
   672 @see MFontGlyphImageStorage
   673 */
   674 void CFontGlyphImageStorage::CleanGlyphImageCache()
   675 	{
   676 	iFontTreeList.ResetAndDestroy();
   677 	iCacheSize = 0;
   678 	}
   679 
   680 /**
   681 @test
   682 
   683 @return Current glyph cache size in bytes.
   684 @see MFontGlyphImageStorage
   685 */
   686 TInt CFontGlyphImageStorage::GlyphCacheSize() const
   687 	{
   688 	return iCacheSize;
   689 	}
   690 
   691 /**
   692 Sets the maximum size in bytes of the glyph cache. Checks the current size of
   693 the cache and sets the maximum cache size if the current cache size is smaller
   694 or equal to aCacheSize.
   695 @param aMaxCacheSize The maximum size in bytes to allow for the glyph cache.
   696 @return KErrNone if the maximum cache size has been changed successfully,
   697 KErrArgument if aMaxCacheSize is smaller than the current cache size. 
   698  */
   699 TInt CFontGlyphImageStorage::SetMaxGlyphCacheSize(TInt aMaxCacheSize)
   700 	{
   701 	if (iCacheSize <= aMaxCacheSize)
   702 		{
   703 		iMaxCacheSize = aMaxCacheSize;
   704 		return KErrNone;
   705 		}
   706 	
   707 	return KErrArgument;
   708 	}
   709 	
   710 /**
   711 @return Max glyph cache size in bytes.
   712 @see MFontGlyphImageStorage
   713 */
   714 TInt CFontGlyphImageStorage::MaxGlyphCacheSize() const
   715 	{
   716 	return iMaxCacheSize;
   717 	}
   718 
   719 /**
   720 Fills aFontListId parameter with font Id in order from most to least usable. 
   721 
   722 @test
   723 @see MFontGlyphImageStorage
   724 
   725 @return KErrNone, if the insertion is successful, otherwise one of the system wide error codes.
   726 */
   727 TInt CFontGlyphImageStorage::FontIdInOrder(RArray<TUint32> & aFontListId) const
   728 	{
   729 	TInt err = KErrNone;
   730 	aFontListId.Reset();
   731 	
   732 	for(TInt index = 0; (index < iFontTreeList.Count()) && (err == KErrNone); index++)
   733 		{
   734 		CFontGlyphTree* glyphTree = iFontTreeList[index];
   735 		err = aFontListId.Append(glyphTree->FontId());
   736 		}
   737 		
   738 	return err;
   739 	}
   740 
   741 /**
   742 Enforce the system to emulate OOM failure. As sequence pre-allocated images will be used.
   743 
   744 @test
   745 @see MFontGlyphImageStorage
   746 */
   747 #ifdef _DEBUG
   748 void CFontGlyphImageStorage::EnforceOOMFailure(TBool aEnforce)
   749 	{
   750 	iEnforceOOM = aEnforce;
   751 	}
   752 #else
   753 void CFontGlyphImageStorage::EnforceOOMFailure(TBool /*aEnforce*/)
   754 	{
   755 	}
   756 #endif
   757 
   758 /**
   759 Retrieves OpenVG images from the font image cache. If the image doesn't exist, the function will create a new one from the bitmap glyph image and 
   760 add it into the font image cache.
   761 Each font corresponds to a particular tree of glyph images.
   762 The function's search is performed in two steps:
   763 	1.	It tries to identify the glyph tree associated with the font. Otherwise a new tree will be created
   764 	2.	Within the tree the function will search for the particular glyph entry. Otherwise a new glyph entry will be created
   765 If the size of the cache exceeds some pre-defined value, the least usable tree with all its entries will be deleted.
   766 If the function fails to place the element into the tree due to shortage of memory, it will 
   767 still try to create VGImages without adding them to the binary tree.
   768 @see	CVgEngine::DrawGlyph
   769 @see 	MFontGlyphImageStorage
   770 
   771 @param	aFontId Unique Font Id.
   772 @param	aGlypCode General Unicode character value.
   773 @param	aGlyphBitmapType A type for the format of a glyph bitmap.
   774 @param	aGlyphImage Glyph bitmap image data.
   775 @param	aGlyphImageSize The size of the glyph bitmap image data.
   776 @param  aImageForeground Pointer to VGImage text foreground handle.
   777 @param  aImageShadow Pointer to VGImage text shadow handle.
   778 @param  aImageOutline Pointer to VGImage text outline handle.
   779 
   780 @pre 	Rendering engine has been constructed.
   781 @post 	Requested  OpenVG images are ready for rendering. 
   782 
   783 @panic DGDIAdapter 1018, if a null glyph image pointer is passed in.
   784 @return On success KErrNone, 
   785 		KErrArgument if passed parameters are not correct,
   786 		KErrNotSupported if functionality is not supported,	otherwise one of the other system-wide error codes.
   787 */
   788 TInt CFontGlyphImageStorage::GlyphImage(TUint32 aFontId, TChar aGlypCode, TGlyphBitmapType aGlyphBitmapType, const TUint8* aGlyphImage, const TSize& aGlyphImageSize, 
   789 				TAny* aImageForeground, TAny* aImageShadow, TAny* aImageOutline)
   790 	{
   791 	if((aGlyphImageSize.iHeight <= 0) || (aGlyphImageSize.iWidth <= 0))
   792 		{
   793 		return KErrArgument;
   794 		}
   795 	GRAPHICS_ASSERT_ALWAYS(aGlyphImage, EDirectGdiPanicInvalidPointer); // maybe needs to change assertion type
   796 	GRAPHICS_ASSERT_ALWAYS(aImageForeground, EDirectGdiPanicInvalidPointer); // maybe needs to change assertion type
   797 	GRAPHICS_ASSERT_ALWAYS((aImageShadow && aImageOutline) || (aGlyphBitmapType != EFourColourBlendGlyphBitmap), EDirectGdiPanicInvalidPointer); // maybe needs to change assertion type
   798 
   799 	TInt res = KErrNone;
   800 	CFontGlyphTree* fontTree = NULL;
   801 	TInt index = 0;
   802 
   803 	for(; index < iFontTreeList.Count(); index++)
   804 		{
   805 		CFontGlyphTree* fontTreeTemp = iFontTreeList[index];
   806 		if(fontTreeTemp->FontId() == aFontId)
   807 			{
   808 			fontTree = fontTreeTemp;
   809 			break;
   810 			}
   811 		}
   812 
   813 	if(!fontTree)
   814 		{ 
   815 #ifdef _DEBUG
   816 		if(!iEnforceOOM)
   817 			{
   818 #endif		
   819 			//there is no tree for that font, thus create one
   820 			TRAP(res, fontTree = CFontGlyphTree::NewL(aFontId, aGlyphBitmapType));
   821 			if(res == KErrNone)
   822 				{
   823 				res = iFontTreeList.Insert(fontTree, 0);
   824 				if(res != KErrNone)
   825 					{
   826 					delete fontTree;
   827 					fontTree = NULL;
   828 					}
   829 				}
   830 #ifdef _DEBUG
   831 			}
   832 #endif		
   833 		}
   834 	else if(index != 0)
   835 		{//reorder the tree
   836 		iFontTreeList.Remove(index);
   837 		res = iFontTreeList.Insert(fontTree, 0);
   838 		if(res != KErrNone)
   839 			{ //we have to delete fontTree as it is not stored anywhere.
   840 			delete fontTree;
   841 			fontTree = NULL;
   842 			}
   843 		}	
   844 
   845 #ifdef _DEBUG	
   846 	if(iEnforceOOM && (res == KErrNone))
   847 		{
   848 		res = KErrNoMemory;	
   849 		}
   850 #endif		
   851 	if(res == KErrNone)
   852 		{
   853 		CleanCacheIfRequired();
   854 		TInt treeCacheSize = fontTree->CacheSize();
   855 		if(aGlyphBitmapType == EFourColourBlendGlyphBitmap)
   856 			{
   857 			TRAP(res, fontTree->GlyphImageEntryL(aGlypCode, aGlyphImage, aGlyphImageSize, iEntryCompound, NULL));
   858 			}
   859 		else
   860 			{
   861 			TRAP(res, fontTree->GlyphImageEntryL(aGlypCode, aGlyphImage, aGlyphImageSize, iEntry, aGlyphBitmapType == EMonochromeGlyphBitmap ? iForegroundData : NULL));
   862 			}	
   863 		if(res == KErrNone)
   864 			{
   865 			iCacheSize += (fontTree->CacheSize() - treeCacheSize);
   866 			if(aGlyphBitmapType == EFourColourBlendGlyphBitmap)
   867 				{
   868 				*(static_cast <VGImage*> (aImageForeground)) = iEntryCompound.iForeground;
   869 				*(static_cast <VGImage*> (aImageShadow)) = iEntryCompound.iShadow;
   870 				*(static_cast <VGImage*> (aImageOutline)) = iEntryCompound.iOutline;
   871 				}
   872 			else
   873 				{
   874 				if(aImageShadow)
   875 					{
   876 					*(static_cast <VGImage*> (aImageShadow)) = VG_INVALID_HANDLE;
   877 					}
   878 				if(aImageOutline)
   879 					{
   880 					*(static_cast <VGImage*> (aImageOutline)) = VG_INVALID_HANDLE;
   881 					}
   882 
   883 				*(static_cast <VGImage*> (aImageForeground)) = iEntry.iForeground;
   884 				}	
   885 			}
   886 		}
   887 		
   888 	//create glyph images for OOM conditions, without putting the entry into the tree
   889 	if((res == KErrNoMemory) && iImagesPreAllocated && (iImageSize.iWidth >= aGlyphImageSize.iWidth ) && (iImageSize.iHeight >= aGlyphImageSize.iHeight))
   890 		{
   891 		const TInt bufferSize = iImageSize.iWidth * iImageSize.iHeight;
   892 		Mem::FillZ(iForegroundData, bufferSize);
   893 		VGImageFormat imageFormat = VG_sL_8;
   894 		TInt vgCompatibleSourceStride = iImageSize.iWidth;
   895 
   896 		if(aGlyphBitmapType == EFourColourBlendGlyphBitmap)
   897 			{
   898 			Mem::FillZ(iShadowData, bufferSize);
   899 			Mem::FillZ(iOutlineData, bufferSize);
   900 			iEntryCompound.iForeground = iImageForeground;
   901 			iEntryCompound.iOutline = iImageOutline;
   902 			iEntryCompound.iShadow = iImageShadow;
   903 			
   904 			vgImageSubData(iEntryCompound.iForeground, iForegroundData, vgCompatibleSourceStride,	imageFormat, 
   905 					0,	0, iImageSize.iWidth, iImageSize.iHeight);
   906 
   907 			vgImageSubData(iEntryCompound.iOutline, iOutlineData, vgCompatibleSourceStride,	imageFormat, 
   908 					0,	0, iImageSize.iWidth, iImageSize.iHeight);
   909 
   910 			vgImageSubData(iEntryCompound.iShadow, iShadowData, vgCompatibleSourceStride,	imageFormat, 
   911 					0,	0, iImageSize.iWidth, iImageSize.iHeight);
   912 
   913 			TRAP_IGNORE(CFontGlyphTree::GlyphImageEntryOOML(aGlyphBitmapType, aGlyphImage, aGlyphImageSize, iEntryCompound, iForegroundData, iShadowData, iOutlineData));
   914 			*(static_cast <VGImage*> (aImageForeground)) = iImageForeground;
   915 			*(static_cast <VGImage*> (aImageShadow)) = iImageShadow;
   916 			*(static_cast <VGImage*> (aImageOutline)) = iImageOutline;
   917 			}
   918 		else
   919 			{
   920 			iEntry.iForeground = iImageForeground;
   921 			vgImageSubData(iEntry.iForeground, iForegroundData, vgCompatibleSourceStride,	imageFormat, 
   922 				0,	0, iImageSize.iWidth, iImageSize.iHeight);
   923 			
   924 			TRAP_IGNORE(CFontGlyphTree::GlyphImageEntryOOML(aGlyphBitmapType, aGlyphImage, aGlyphImageSize, iEntry, iForegroundData, NULL, NULL));
   925 			*(static_cast <VGImage*> (aImageForeground)) = iImageForeground;
   926 			}	
   927 		}
   928 	
   929 	return res;
   930 	}
   931 
   932 /**
   933 Creates VGImages for use in low memory conditions
   934 */
   935 TInt CFontGlyphImageStorage::PreAllocateImages()
   936 	{
   937 	iImageSize = KMaxSizeImageOOM;
   938 
   939 #ifdef DRAWGLYPH_MULTIPLY_MODE
   940 	// For image_multiply mode need 32bits for each glyph instrad of 8 for non-multiply mode.
   941 	const TInt bufferSize = iImageSize.iWidth * iImageSize.iHeight * 4;
   942 #else
   943 	const TInt bufferSize = iImageSize.iWidth * iImageSize.iHeight;
   944 #endif
   945 	if(!iForegroundData)
   946 		{
   947 		iForegroundData = (TUint8*) User::Alloc(bufferSize);
   948 		if(!iForegroundData)
   949 			{
   950 			return KErrNoMemory;
   951 			}
   952 		}
   953 	
   954 	if(!iShadowData)
   955 		{
   956 		iShadowData = (TUint8*) User::Alloc(bufferSize);
   957 		if(!iShadowData)
   958 			{
   959 			return KErrNoMemory;
   960 			}
   961 		}
   962 
   963 	if(!iOutlineData)
   964 		{
   965 		iOutlineData = (TUint8*) User::Alloc(bufferSize);
   966 		if(!iOutlineData)
   967 			{
   968 			return KErrNoMemory;
   969 			}
   970 		}
   971 
   972 	const VGImageFormat imageFormat = VG_sL_8;
   973 	if(iImageForeground == VG_INVALID_HANDLE)
   974 		{
   975 		
   976 		iImageForeground = vgCreateImage(imageFormat,
   977 	                              iImageSize.iWidth, 
   978 	                              iImageSize.iHeight,
   979 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
   980 		if(iImageForeground == VG_INVALID_HANDLE)
   981 			{
   982 			return KErrNoMemory;
   983 			}
   984 		}
   985 
   986 	if(iImageShadow == VG_INVALID_HANDLE)
   987 		{
   988 		iImageShadow = vgCreateImage(imageFormat,
   989 	                              iImageSize.iWidth, 
   990 	                              iImageSize.iHeight,
   991 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
   992 		if(iImageShadow == VG_INVALID_HANDLE)
   993 			{
   994 			return KErrNoMemory;
   995 			}
   996 		}
   997 
   998 	if(iImageOutline == VG_INVALID_HANDLE)
   999 		{
  1000 		iImageOutline = vgCreateImage(imageFormat,
  1001 	                              iImageSize.iWidth, 
  1002 	                              iImageSize.iHeight,
  1003 	                              VG_IMAGE_QUALITY_NONANTIALIASED);
  1004 		if(iImageOutline == VG_INVALID_HANDLE)
  1005 			{
  1006 			return KErrNoMemory;
  1007 			}
  1008 		}
  1009 
  1010 	iImagesPreAllocated = ETrue;	
  1011 	return KErrNone;
  1012 	}
  1013 
  1014 /**
  1015 Deletes all pre-allocated images and frees buffers. 
  1016 */
  1017 void CFontGlyphImageStorage::DeletePreAllocatedImages()
  1018 	{
  1019 	if(iForegroundData)
  1020 		{
  1021 		User::Free(iForegroundData);
  1022 		iForegroundData = NULL;
  1023 		}
  1024 
  1025 	if(iShadowData)
  1026 		{
  1027 		User::Free(iShadowData);
  1028 		iShadowData = NULL;
  1029 		}
  1030 
  1031 	if(iOutlineData)
  1032 		{
  1033 		User::Free(iOutlineData);
  1034 		iOutlineData = NULL;
  1035 		}
  1036 		
  1037 	if(iImageForeground != VG_INVALID_HANDLE)
  1038 		{
  1039 		vgDestroyImage(iImageForeground);
  1040 		iImageForeground = VG_INVALID_HANDLE;
  1041 		}
  1042 		
  1043 	if(iImageShadow != VG_INVALID_HANDLE)
  1044 		{
  1045 		vgDestroyImage(iImageShadow);
  1046 		iImageShadow = VG_INVALID_HANDLE;
  1047 		}
  1048 		
  1049 	if(iImageOutline != VG_INVALID_HANDLE)
  1050 		{
  1051 		vgDestroyImage(iImageOutline);
  1052 		iImageOutline = VG_INVALID_HANDLE;
  1053 		}
  1054 	iImagesPreAllocated = EFalse;	
  1055 	}