os/graphics/fbs/fontandbitmapserver/tfbs/tglyphatlas.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2009-2010 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 /**
    17  @file
    18  @internalComponent - Internal Symbian test code
    19 */
    20 
    21 #include "tglyphatlas.h"
    22 #include "TFBS.H"
    23 #include "glyphatlastestwrapper.h"
    24 
    25 _LIT(KTypefaceName, "DejaVu Sans Condensed");
    26 _LIT(KMonoTypefaceName, "DejaVu Sans Mono");
    27 const TInt KNumGlyphCodesLatin = 96;
    28 
    29 
    30 CTGlyphAtlas::CTGlyphAtlas(CTestStep* aStep):
    31 	CTGraphicsBase(aStep),
    32 	iFbs(NULL),
    33 	iTs(NULL),
    34 	iGlyphCodesLatin(NULL),
    35 	iFont(NULL)
    36 	{
    37 	}
    38 
    39 void CTGlyphAtlas::ConstructL()
    40 	{
    41 	iFbs = RFbsSession::GetSession();
    42 	iTs = (CFbsTypefaceStore*)CFbsTypefaceStore::NewL(NULL);
    43 	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont, TFontSpec(KTypefaceName, 15)));
    44 	User::LeaveIfError(iTs->GetNearestFontToDesignHeightInPixels((CFont*&)iFont2, TFontSpec(KMonoTypefaceName, 8)));
    45 	
    46 	iGlyphCodesLatin = new(ELeave) TUint[KNumGlyphCodesLatin];
    47 	for (TInt ii = 0; ii < KNumGlyphCodesLatin; ++ii)
    48 		{
    49 		iGlyphCodesLatin[ii] = ii+32; // ASCII characters from 0020 to 007F
    50 		}
    51 
    52 	INFO_PRINTF1(_L("FBSERV Glyph Atlas Testing"));
    53 	}
    54 
    55 CTGlyphAtlas::~CTGlyphAtlas()
    56 	{
    57 	if (iTs)
    58 		{
    59 		iTs->ReleaseFont(iFont);
    60 		}
    61 	delete iTs;
    62 	delete[] iGlyphCodesLatin;
    63 	}
    64 
    65 void CTGlyphAtlas::RunTestCaseL(TInt aCurTestCase)
    66 	{
    67 	((CTGlyphAtlasStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
    68 	switch(aCurTestCase)
    69 		{
    70 	case 1:
    71 		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0663"));
    72 		TestFullCache();
    73 		break;
    74 	case 2:
    75 		((CTGlyphAtlasStep*)iStep)->SetTestStepID(_L("GRAPHICS-FBSERV-0664"));
    76 		TestFontReleased();
    77 		break;
    78 	default:
    79 		((CTGlyphAtlasStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
    80 		((CTGlyphAtlasStep*)iStep)->CloseTMSGraphicsStep();
    81 		TestComplete();		
    82 		break;
    83 		}
    84 	((CTGlyphAtlasStep*)iStep)->RecordTestResultL();
    85 	}
    86 
    87 /**
    88 @SYMTestCaseID		GRAPHICS-FBSERV-0663
    89 @SYMTestPriority	High
    90 @SYMTestType		UT
    91 @SYMTestStatus		Implemented
    92 @SYMPREQ			PREQ2678
    93 
    94 @SYMTestCaseDesc
    95 	Shows that when the glyph atlas reaches its memory limit, any new added 
    96 	glyphs will cause the eviction of the least recently used glyphs.
    97 	The new glyph will be added successfully.
    98 
    99 @SYMTestActions
   100 	i. Create a glyph atlas with a memory limit of 1000 bytes.
   101 	ii. Add glyphs to the atlas such that its memory consumption reaches the limit.
   102 	iii. Add one more glyph.
   103 	iv. Call CGlyphAtlas::GetGlyph() for the last glyph added.
   104 	v. Call CGlyphAtlas::GetGlyph() for the least recently used glyphs to check 
   105 		that it has been evicted.
   106 	vi. Delete glyph atlas
   107 
   108 @SYMTestExpectedResults
   109 	Each glyph is added successfully.
   110 	CGlyphAtlas::GetGlyph() returns KErrNone for the last glyph added.
   111 	CGlyphAtlas::GetGlyph() returns KErrNotFound for the least recently used glyph.
   112 */
   113 void CTGlyphAtlas::TestFullCache()
   114 	{
   115 	INFO_PRINTF1(_L("Test full cache eviction"));
   116 
   117 	__UHEAP_MARK;
   118 	// Fill cache up using expected size of glyph using AddGlyph.
   119 	const TInt KMaxAtlasSizeInBytes = 1000;
   120 	CGlyphAtlasTestWrapper* atlas = NULL;
   121 	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KMaxAtlasSizeInBytes));
   122 	TESTNOERROR(ret);
   123 	if (KErrNone != ret)
   124 		{
   125 		return;
   126 		}
   127 	TOpenFontCharMetrics charMetrics;
   128 	TGlyphImageInfo imageInfo;
   129 	TSize bitmapSize;
   130 	const TUint8* bitmapData = NULL;
   131 	TInt glyphIndex = 0;
   132 	TBool atlasFull = EFalse;
   133 	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
   134 	// Fill up atlas by adding glyphs.
   135 	// Next glyph shold tip the atlas over the memory limit.
   136 	// Glyphs are added in ascending glyph code order.
   137 	// Leave at least one glyph so that we can guarantee that we can add one more unique glyph.
   138 	while (glyphIndex < KNumGlyphCodesLatin-1 && !atlasFull)
   139 		{
   140 		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
   141 		TInt sizeInBytes = charMetrics.Height() * charMetrics.Width();
   142 		if (atlas->SizeInBytes() + sizeInBytes <= KMaxAtlasSizeInBytes)
   143 			{
   144 			CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex++], charMetrics);
   145 			TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   146 			}
   147 		else
   148 			{
   149 			atlasFull = ETrue;
   150 			}
   151 		}
   152 	TEST(atlasFull);
   153 
   154 	// check least recently used page contains the first glyph in glyph codes
   155 	TUint leastUsedGlyphCode = iGlyphCodesLatin[0];
   156 	TEST(atlas->LruPageContainsGlyph(leastUsedGlyphCode));
   157 
   158 	// To ensure that the test does not pass if a FIFO eviction policy occurs,
   159 	// get the least recently used glyph so that it is moved internally.
   160 	TESTNOERROR(atlas->GetGlyph(*bmFont, leastUsedGlyphCode, imageInfo));
   161 
   162 	// glyphIndex, bitmapData and charMetrics now current for next glyph which 
   163 	// will take the atlas over the cache limit.
   164 	CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   165 	TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   166 
   167 	// check that searching for most recently added glyph is successful
   168 	TGlyphImageInfo newInfo;
   169 	TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[glyphIndex], newInfo));
   170 
   171 	// check atlas size is still under the limit
   172 	TEST(atlas->SizeInBytes() <= KMaxAtlasSizeInBytes);
   173 
   174 	// check that the pages which were evicted contained the least used glyphs
   175 	// i.e. searching for these returns KErrNotFound
   176 	TInt err = KErrNotFound;
   177 	TInt index = 1;
   178 	for (; KErrNotFound == err && index <= glyphIndex; ++index)
   179 		{
   180 		err = atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo);
   181 		}
   182 	TESTNOERROR(err);
   183 	// first found glyph should be greater than glyph at index 1
   184 	TEST(index-1 > 1);
   185 	
   186 	// check that the remaining pages contained the least used glyphs
   187 	for (; index <= glyphIndex; ++index)
   188 		{
   189 		TESTNOERROR(atlas->GetGlyph(*bmFont, iGlyphCodesLatin[index], newInfo));
   190 		}
   191 
   192 	delete atlas;
   193 	__UHEAP_MARKEND;
   194 	}
   195 
   196 
   197 /**
   198 @SYMTestCaseID		GRAPHICS-FBSERV-0664
   199 @SYMTestPriority	High
   200 @SYMTestType		UT
   201 @SYMTestStatus		Implemented
   202 @SYMPREQ			PREQ2678
   203 
   204 @SYMTestCaseDesc
   205 	Shows that CGlyphAtlas::FontReleased() does actually delete all the glyphs 
   206 	associated with the released font and leaves glyphs associated with other 
   207 	fonts untouched.
   208 
   209 @SYMTestActions
   210 	i. Create a glyph atlas with no memory limit.
   211 	ii. Add glyphs for two different fonts to the atlas.
   212 	iii. Check all glyphs for both fonts were successfully added.
   213 	iv. Call CGlyphAtlas::ReleaseFont for one of the fonts.
   214 	v. Check that there are no glyphs associated with the released font.
   215 	vi. Call CGlyphAtlas::ReleaseFont for the remaining font.
   216 	vii Check that there are no glyphs associated with the released font and 
   217 		that the atlas is empty.
   218 	viii Delete the glyph atlas.
   219 	
   220 @SYMTestExpectedResults
   221 	After each font is released, there are no glyphs associated with that font 
   222 	left in the atlas.
   223 */
   224 void CTGlyphAtlas::TestFontReleased()
   225 	{
   226 	INFO_PRINTF1(_L("Test behaviour of CGlyphAtlas::FontReleased()"));
   227 
   228 	__UHEAP_MARK;
   229 	CGlyphAtlasTestWrapper* atlas = NULL;
   230 	TRAPD(ret, atlas = CGlyphAtlasTestWrapper::NewL(KGlyphAtlasNoCacheLimit));
   231 	TESTNOERROR(ret);
   232 	if (KErrNone != ret)
   233 		{
   234 		return;
   235 		}
   236 	TOpenFontCharMetrics charMetrics;
   237 	TGlyphImageInfo imageInfo;
   238 	TSize bitmapSize;
   239 	const TUint8* bitmapData = NULL;
   240 	CBitmapFont* bmFont = CTFbsFont::FontAddress(iFont);
   241 	CBitmapFont* bmFont2 = CTFbsFont::FontAddress(iFont2);
   242 	for (TInt glyphIndex = 0; glyphIndex < KNumGlyphCodesLatin; ++glyphIndex)
   243 		{
   244 		iFont->GetCharacterData(iGlyphCodesLatin[glyphIndex], charMetrics, bitmapData, bitmapSize);
   245 		CGlyphAtlas::TAddGlyphArgs args(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   246 		TESTNOERROR(atlas->AddGlyph(*bmFont, args, imageInfo));
   247 
   248 		iFont2->GetCharacterData(iGlyphCodesLatin[KNumGlyphCodesLatin-1-glyphIndex], charMetrics, bitmapData, bitmapSize);
   249 		CGlyphAtlas::TAddGlyphArgs args2(bitmapData, iGlyphCodesLatin[glyphIndex], charMetrics);
   250 		TESTNOERROR(atlas->AddGlyph(*bmFont2, args2, imageInfo));
   251 		}
   252 	// check there are font entries for these 2 fonts
   253 	TEST(2 == atlas->FontCount());
   254 
   255 	// check actual number of glyphs in atlas for each font is as expected
   256 	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont));
   257 	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
   258 	TEST(2*KNumGlyphCodesLatin == atlas->GlyphCount());
   259 
   260 	// release one font and check number of glyphs in atlas for each font 
   261 	// is as expected
   262 	atlas->FontReleased(*bmFont);
   263 	TEST(1 == atlas->FontCount());
   264 	TEST(0 == atlas->GlyphCountByFont(bmFont));
   265 	TEST(KNumGlyphCodesLatin == atlas->GlyphCountByFont(bmFont2));
   266 	TEST(KNumGlyphCodesLatin == atlas->GlyphCount());
   267 
   268 	// release one font and check number of glyphs in atlas for each font 
   269 	// is as expected
   270 	atlas->FontReleased(*bmFont2);
   271 	TEST(0 == atlas->FontCount());
   272 	TEST(0 == atlas->GlyphCountByFont(bmFont));
   273 	TEST(0 == atlas->GlyphCountByFont(bmFont2));
   274 	TEST(0 == atlas->GlyphCount());
   275 
   276 	delete atlas;
   277 
   278 	__UHEAP_MARKEND;
   279 	}
   280 
   281 
   282 
   283 //--------------
   284 __CONSTRUCT_STEP__(GlyphAtlas)