os/graphics/fbs/fontandbitmapserver/tfbs/tglyphatlas.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/fbs/fontandbitmapserver/tfbs/tglyphatlas.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,284 @@
     1.4 +// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +/**
    1.20 + @file
    1.21 + @internalComponent - Internal Symbian test code
    1.22 +*/
    1.23 +
    1.24 +#include "tglyphatlas.h"
    1.25 +#include "TFBS.H"
    1.26 +#include "glyphatlastestwrapper.h"
    1.27 +
    1.28 +_LIT(KTypefaceName, "DejaVu Sans Condensed");
    1.29 +_LIT(KMonoTypefaceName, "DejaVu Sans Mono");
    1.30 +const TInt KNumGlyphCodesLatin = 96;
    1.31 +
    1.32 +
    1.33 +CTGlyphAtlas::CTGlyphAtlas(CTestStep* aStep):
    1.34 +	CTGraphicsBase(aStep),
    1.35 +	iFbs(NULL),
    1.36 +	iTs(NULL),
    1.37 +	iGlyphCodesLatin(NULL),
    1.38 +	iFont(NULL)
    1.39 +	{
    1.40 +	}
    1.41 +
    1.42 +void CTGlyphAtlas::ConstructL()
    1.43 +	{
    1.44 +	iFbs = RFbsSession::GetSession();
    1.45 +	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
    1.46 +	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
    1.47 +	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KMonoTypefaceName, 8)));
    1.48 +	
    1.49 +	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
    1.50 +	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
    1.51 +		{
    1.52 +		iGlyphCodesLatin[ii] = ii+32; // ASCII characters from 0020 to 007F
    1.53 +		}
    1.54 +
    1.55 +	INFO_PRINTF1(_L("FBSERV Glyph Atlas Testing"));
    1.56 +	}
    1.57 +
    1.58 +CTGlyphAtlas::~CTGlyphAtlas()
    1.59 +	{
    1.60 +	if (iTs)
    1.61 +		{
    1.62 +		iTs->ReleaseFont(iFont);
    1.63 +		}
    1.64 +	delete iTs;
    1.65 +	delete[] iGlyphCodesLatin;
    1.66 +	}
    1.67 +
    1.68 +void CTGlyphAtlas::RunTestCaseL(TInt aCurTestCase)
    1.69 +	{
    1.70 +	((CTGlyphAtlasStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
    1.71 +	switch(aCurTestCase)
    1.72 +		{
    1.73 +	case 1:
    1.74 +		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0663"));
    1.75 +		TestFullCache();
    1.76 +		break;
    1.77 +	case 2:
    1.78 +		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0664"));
    1.79 +		TestFontReleased();
    1.80 +		break;
    1.81 +	default:
    1.82 +		((CTGlyphAtlasStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
    1.83 +		((CTGlyphAtlasStep*)iStep)->CloseTMSGraphicsStep();
    1.84 +		TestComplete();		
    1.85 +		break;
    1.86 +		}
    1.87 +	((CTGlyphAtlasStep*)iStep)->RecordTestResultL();
    1.88 +	}
    1.89 +
    1.90 +/**
    1.91 +@SYMTestCaseID		GRAPHICS-FBSERV-0663
    1.92 +@SYMTestPriority	High
    1.93 +@SYMTestType		UT
    1.94 +@SYMTestStatus		Implemented
    1.95 +@SYMPREQ			PREQ2678
    1.96 +
    1.97 +@SYMTestCaseDesc
    1.98 +	Shows that when the glyph atlas reaches its memory limit, any new added 
    1.99 +	glyphs will cause the eviction of the least recently used glyphs.
   1.100 +	The new glyph will be added successfully.
   1.101 +
   1.102 +@SYMTestActions
   1.103 +	i. Create a glyph atlas with a memory limit of 1000 bytes.
   1.104 +	ii. Add glyphs to the atlas such that its memory consumption reaches the limit.
   1.105 +	iii. Add one more glyph.
   1.106 +	iv. Call CGlyphAtlas::GetGlyph() for the last glyph added.
   1.107 +	v. Call CGlyphAtlas::GetGlyph() for the least recently used glyphs to check 
   1.108 +		that it has been evicted.
   1.109 +	vi. Delete glyph atlas
   1.110 +
   1.111 +@SYMTestExpectedResults
   1.112 +	Each glyph is added successfully.
   1.113 +	CGlyphAtlas::GetGlyph() returns KErrNone for the last glyph added.
   1.114 +	CGlyphAtlas::GetGlyph() returns KErrNotFound for the least recently used glyph.
   1.115 +*/
   1.116 +void CTGlyphAtlas::TestFullCache()
   1.117 +	{
   1.118 +	INFO_PRINTF1(_L("Test full cache eviction"));
   1.119 +
   1.120 +	__UHEAP_MARK;
   1.121 +	// Fill cache up using expected size of glyph using AddGlyph.
   1.122 +	const TInt KMaxAtlasSizeInBytes = 1000;
   1.123 +	CGlyphAtlasTestWrapper* atlas = NULL;
   1.124 +	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KMaxAtlasSizeInBytes));
   1.125 +	TESTNOERROR(ret);
   1.126 +	if (KErrNone != ret)
   1.127 +		{
   1.128 +		return;
   1.129 +		}
   1.130 +	TOpenFontCharMetrics charMetrics;
   1.131 +	TGlyphImageInfo imageInfo;
   1.132 +	TSize bitmapSize;
   1.133 +	const TUint8* bitmapData = NULL;
   1.134 +	TInt glyphIndex = 0;
   1.135 +	TBool atlasFull = EFalse;
   1.136 +	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
   1.137 +	// Fill up atlas by adding glyphs.
   1.138 +	// Next glyph shold tip the atlas over the memory limit.
   1.139 +	// Glyphs are added in ascending glyph code order.
   1.140 +	// Leave at least one glyph so that we can guarantee that we can add one more unique glyph.
   1.141 +	while (glyphIndex < KNumGlyphCodesLatin-1 && !atlasFull)
   1.142 +		{
   1.143 +		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
   1.144 +		TInt sizeInBytes = charMetrics.Height() * charMetrics.Width();
   1.145 +		if (atlas->SizeInBytes() + sizeInBytes <= KMaxAtlasSizeInBytes)
   1.146 +			{
   1.147 +			CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex++], charMetrics);
   1.148 +			TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   1.149 +			}
   1.150 +		else
   1.151 +			{
   1.152 +			atlasFull = ETrue;
   1.153 +			}
   1.154 +		}
   1.155 +	TEST(atlasFull);
   1.156 +
   1.157 +	// check least recently used page contains the first glyph in glyph codes
   1.158 +	TUint leastUsedGlyphCode = iGlyphCodesLatin[0];
   1.159 +	TEST(atlas->LruPageContainsGlyph(leastUsedGlyphCode));
   1.160 +
   1.161 +	// To ensure that the test does not pass if a FIFO eviction policy occurs,
   1.162 +	// get the least recently used glyph so that it is moved internally.
   1.163 +	TESTNOERROR(atlas->GetGlyph(*bmFont, leastUsedGlyphCode, imageInfo));
   1.164 +
   1.165 +	// glyphIndex, bitmapData and charMetrics now current for next glyph which 
   1.166 +	// will take the atlas over the cache limit.
   1.167 +	CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   1.168 +	TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   1.169 +
   1.170 +	// check that searching for most recently added glyph is successful
   1.171 +	TGlyphImageInfo newInfo;
   1.172 +	TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[glyphIndex], newInfo));
   1.173 +
   1.174 +	// check atlas size is still under the limit
   1.175 +	TEST(atlas->SizeInBytes() <= KMaxAtlasSizeInBytes);
   1.176 +
   1.177 +	// check that the pages which were evicted contained the least used glyphs
   1.178 +	// i.e. searching for these returns KErrNotFound
   1.179 +	TInt err = KErrNotFound;
   1.180 +	TInt index = 1;
   1.181 +	for (; KErrNotFound == err && index <= glyphIndex; ++index)
   1.182 +		{
   1.183 +		err = atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo);
   1.184 +		}
   1.185 +	TESTNOERROR(err);
   1.186 +	// first found glyph should be greater than glyph at index 1
   1.187 +	TEST(index-1 > 1);
   1.188 +	
   1.189 +	// check that the remaining pages contained the least used glyphs
   1.190 +	for (; index <= glyphIndex; ++index)
   1.191 +		{
   1.192 +		TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo));
   1.193 +		}
   1.194 +
   1.195 +	delete atlas;
   1.196 +	__UHEAP_MARKEND;
   1.197 +	}
   1.198 +
   1.199 +
   1.200 +/**
   1.201 +@SYMTestCaseID		GRAPHICS-FBSERV-0664
   1.202 +@SYMTestPriority	High
   1.203 +@SYMTestType		UT
   1.204 +@SYMTestStatus		Implemented
   1.205 +@SYMPREQ			PREQ2678
   1.206 +
   1.207 +@SYMTestCaseDesc
   1.208 +	Shows that CGlyphAtlas::FontReleased() does actually delete all the glyphs 
   1.209 +	associated with the released font and leaves glyphs associated with other 
   1.210 +	fonts untouched.
   1.211 +
   1.212 +@SYMTestActions
   1.213 +	i. Create a glyph atlas with no memory limit.
   1.214 +	ii. Add glyphs for two different fonts to the atlas.
   1.215 +	iii. Check all glyphs for both fonts were successfully added.
   1.216 +	iv. Call CGlyphAtlas::ReleaseFont for one of the fonts.
   1.217 +	v. Check that there are no glyphs associated with the released font.
   1.218 +	vi. Call CGlyphAtlas::ReleaseFont for the remaining font.
   1.219 +	vii Check that there are no glyphs associated with the released font and 
   1.220 +		that the atlas is empty.
   1.221 +	viii Delete the glyph atlas.
   1.222 +	
   1.223 +@SYMTestExpectedResults
   1.224 +	After each font is released, there are no glyphs associated with that font 
   1.225 +	left in the atlas.
   1.226 +*/
   1.227 +void CTGlyphAtlas::TestFontReleased()
   1.228 +	{
   1.229 +	INFO_PRINTF1(_L("Test behaviour of CGlyphAtlas::FontReleased()"));
   1.230 +
   1.231 +	__UHEAP_MARK;
   1.232 +	CGlyphAtlasTestWrapper* atlas = NULL;
   1.233 +	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KGlyphAtlasNoCacheLimit));
   1.234 +	TESTNOERROR(ret);
   1.235 +	if (KErrNone != ret)
   1.236 +		{
   1.237 +		return;
   1.238 +		}
   1.239 +	TOpenFontCharMetrics charMetrics;
   1.240 +	TGlyphImageInfo imageInfo;
   1.241 +	TSize bitmapSize;
   1.242 +	const TUint8* bitmapData = NULL;
   1.243 +	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
   1.244 +	CBitmapFont* bmFont2 = CTFbsFont::FontAddress(iFont2);
   1.245 +	for (TInt glyphIndex = 0; glyphIndex < KNumGlyphCodesLatin; ++glyphIndex)
   1.246 +		{
   1.247 +		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
   1.248 +		CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   1.249 +		TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   1.250 +
   1.251 +		iFont2->GetCharacterData(iGlyphCodesLatin[KNumGlyphCodesLatin-1-glyphIndex], charMetrics, bitmapData, bitmapSize);
   1.252 +		CGlyphAtlas::TAddGlyphArgs args2(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   1.253 +		TESTNOERROR(atlas->AddGlyph(*bmFont2, args2, imageInfo));
   1.254 +		}
   1.255 +	// check there are font entries for these 2 fonts
   1.256 +	TEST(2 == atlas->FontCount());
   1.257 +
   1.258 +	// check actual number of glyphs in atlas for each font is as expected
   1.259 +	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont));
   1.260 +	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
   1.261 +	TEST(2*KNumGlyphCodesLatin == atlas->GlyphCount());
   1.262 +
   1.263 +	// release one font and check number of glyphs in atlas for each font 
   1.264 +	// is as expected
   1.265 +	atlas->FontReleased(*bmFont);
   1.266 +	TEST(1 == atlas->FontCount());
   1.267 +	TEST(0 == atlas->GlyphCountByFont(bmFont));
   1.268 +	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
   1.269 +	TEST(KNumGlyphCodesLatin == atlas->GlyphCount());
   1.270 +
   1.271 +	// release one font and check number of glyphs in atlas for each font 
   1.272 +	// is as expected
   1.273 +	atlas->FontReleased(*bmFont2);
   1.274 +	TEST(0 == atlas->FontCount());
   1.275 +	TEST(0 == atlas->GlyphCountByFont(bmFont));
   1.276 +	TEST(0 == atlas->GlyphCountByFont(bmFont2));
   1.277 +	TEST(0 == atlas->GlyphCount());
   1.278 +
   1.279 +	delete atlas;
   1.280 +
   1.281 +	__UHEAP_MARKEND;
   1.282 +	}
   1.283 +
   1.284 +
   1.285 +
   1.286 +//--------------
   1.287 +__CONSTRUCT_STEP__(GlyphAtlas)