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