// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// This test is designed to run in environment with monotype font support.
// To set up environment launch ityperast.cmd from epoc32\winscw\, and
// then follow instruction on the screen.
//
//
#include "tglyphimagecache.h"
#include <graphics/directgdiengine.h>
#include <e32base.h>
#include <VG/openvg.h>
// The size of the target in pixels to use for these tests
const TSize KGlyphCacheWindowSize(400, 400);
enum TFontParam
{
ENormal,
EUnderline = 0x1,
EStrikeThrough = 0x2,
EBold = 0x4,
EUnderlineBold = 0x5,
EItalic = 0x8,
EItalicStrikeThrough = 0xa,
};
class TFontType
{
public:
TInt iFontSize;
TFontParam iFontParam;
};
LOCAL_C void CleanCache(TAny* aPtr)
{
MFontGlyphImageStorage* glyphImageStorage = reinterpret_cast<MFontGlyphImageStorage*> (aPtr);
glyphImageStorage->CleanGlyphImageCache();
}
CTGlyphImageCache::CTGlyphImageCache()
{
SetTestStepName(KTGlyphImageCacheStep);
}
CTGlyphImageCache::~CTGlyphImageCache()
{
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9201
REQ9202
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Test requests Glyph Image elements from storage according their Glyph Key.
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
Create Font Image Storage. In the cycle request aGlyph Image entry for a particular Glyph
code and a font ID.
Delete Glyph Storage.
@SYMTestExpectedResults
GlyphImage function must succeed; foreground, shadow and outlined images (if applicable) must be created
*/
void CTGlyphImageCache::TestRetrieveEntryL(MFontGlyphImageStorage* aGlyphStorage, TGlyphBitmapType aGlyphType)
{
if(!aGlyphStorage)
return;
_LIT(KTestName, "GlyphCache_RetrieveEntry");
if(!iRunningOomTests)
{
INFO_PRINTF1(KTestName);
}
TSize size(20, 30);
TInt bufferLength = size.iWidth * size.iHeight;
TUint8* buffer = (TUint8*)User::AllocL(bufferLength);
CleanupStack::PushL(buffer);
if(aGlyphType == EMonochromeGlyphBitmap)
{//to make decoding mechanizm work properly we need to fill the buffer
Mem::Fill(buffer, bufferLength, 0x1);
}
TInt fontListId[] =
{
1, 5, 3, 5
};
TInt numFont = sizeof(fontListId) / sizeof(fontListId[0]);
TUint charCodeList[] =
{
1, 2, 3, 2, 3,
};
TInt numGlyphCode = sizeof(charCodeList) / sizeof(charCodeList[0]);
for(TInt jj = 0; jj < numFont; jj++)
{
TInt fontId = fontListId[jj];
for(TInt ii = 0; ii < numGlyphCode; ii++)
{
TChar glyphCode = TChar(charCodeList[ii]);
VGImage foregroundImg = VG_INVALID_HANDLE;
VGImage shadowImg = VG_INVALID_HANDLE;
VGImage outlineImg = VG_INVALID_HANDLE;
TBool res = aGlyphStorage->GlyphImage(fontId, glyphCode, aGlyphType, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERROR(res);
if(res != KErrNone)
{
User::Leave(res);
}
else
{
TEST(foregroundImg);
if(aGlyphType == EFourColourBlendGlyphBitmap)
{
TEST(shadowImg);
TEST(outlineImg);
}
}
}
}
CleanupStack::PopAndDestroy(buffer);
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9201
REQ9202
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Drawing monochrome, anti-aliased and four colour fonts with different styles
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
Text is output with different effects (strikethrough, underline) and orientation
(horizontal, vertical up, vertical down) and at different sizes and positions.
Clip region is also specified.
@SYMTestExpectedResults
Test and reference images must match
*/
void CTGlyphImageCache::TestDrawGlyphL(MFontGlyphImageStorage* aGlyphStorage, TGlyphBitmapType aGlyphBitmapType, DrawTextDirection aDirection, DrawTextAdjustment aDrawAdjustment, TBool aClipText)
{
_LIT(KTestNameTemplate, "DrawGlyph%S_Dir%d_Clip%d_Adjust%d");
TBuf<128> testName;
_LIT(KTextOutput, "Hello world! Hello world! Hello world! Hello world! Hello world! Hello world!");
switch(aGlyphBitmapType)
{
case EMonochromeGlyphBitmap:
_LIT(KMonochromeName, "Monochrome");
testName.Format(KTestNameTemplate, &KMonochromeName, aDirection, aClipText, aDrawAdjustment);
break;
case EAntiAliasedGlyphBitmap:
_LIT(KAntiAliasedName, "AntiAliased");
testName.Format(KTestNameTemplate, &KAntiAliasedName, aDirection, aClipText, aDrawAdjustment);
break;
case EFourColourBlendGlyphBitmap:
_LIT(KFourColourName, "FourColour");
testName.Format(KTestNameTemplate, &KFourColourName, aDirection, aClipText, aDrawAdjustment);
break;
default:
User::Leave(KErrNotSupported);
break;
}
if(!iRunningOomTests)
{
INFO_PRINTF1(testName);
}
ResetGc();
_LIT(KTestFontTypefaceName,"DejaVu Sans Condensed");
const TFontType fontType[] =
{
18, EStrikeThrough, 48, EUnderline, 16, EItalic, 78, EItalicStrikeThrough,
18, EStrikeThrough, 48, EUnderlineBold, 16, ENormal, 78, EStrikeThrough, 78, EBold,
};
TPoint pt(5, 5);
TInt *coord = & (pt.iY);
TSize size = iGdiTarget->SizeInPixels();
TRect rect = size;
rect.Shrink(20, 5);
RRegion region(rect);
TRect rect1;
if(aDirection == EDrawTextHorizontal)
{
rect1 = TRect(size.iWidth / 2 - 40, 40, size.iWidth / 2 + 40, size.iHeight - 40);
}
else
{
rect1 = TRect(20, size.iHeight / 2 - 40, size.iWidth - 20, size.iHeight / 2 + 40);
}
region.SubRect(rect1);
if(aDirection == EDrawTextVerticalUp || aDirection == EDrawTextVerticalDown)
{
if(aDirection == EDrawTextVerticalUp)
{
pt.iY = size.iHeight - 5;
}
coord = &(pt.iX);
}
TInt arraySize = sizeof(fontType) / sizeof(fontType[0]);
for(TInt ii = 0; ii < arraySize; ii++)
{
CFont *font = NULL;
TFontSpec fspec(KTestFontTypefaceName, fontType[ii].iFontSize);
fspec.iFontStyle.SetBitmapType(aGlyphBitmapType);
iGc->Reset();
if(aClipText)
{
iGc->SetClippingRegion(region);
}
if(aGlyphBitmapType == EFourColourBlendGlyphBitmap)
{
fspec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
fspec.iFontStyle.SetEffects(FontEffect::EOutline, ETrue);
fspec.iFontStyle.SetEffects(FontEffect::EDropShadow, ETrue);
TRgb shadowColor = TRgb(0, 0, 255);
iGc->SetTextShadowColor(shadowColor);
TEST(shadowColor == iGc->TextShadowColor());
iGc->SetBrushColor(TRgb(255, 0, 0));
TEST(TRgb(255, 0, 0) == iGc->BrushColor());
}
else
{
iGc->SetBrushStyle(DirectGdi::ENullBrush);
iGc->SetPenStyle(DirectGdi::ESolidPen);
}
iGc->SetPenColor(TRgb(0, 255, 0));
if(fontType[ii].iFontParam & EItalic)
{
fspec.iFontStyle.SetPosture(EPostureItalic);
}
if(fontType[ii].iFontParam & EBold)
{
fspec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
}
User::LeaveIfError(iFontStore->GetNearestFontToDesignHeightInPixels((CFont*&) font, fspec));
if(iUseDirectGdi)
{
if(ii == 2)
{
iGc->SetFontNoDuplicate(font);
(reinterpret_cast <CTestDirectGdiContext*> (iGc))->NoJustifyAutoUpdate();
}
else
{
iGc->SetFont(font);
iGc->SetFontNoDuplicate(font);//shoudn't have any impact
(reinterpret_cast <CTestDirectGdiContext*> (iGc))->SetJustifyAutoUpdate();
}
}
else
{
iGc->SetFont(font);
iGc->SetFontNoDuplicate(font);//shoudn't have any impact
}
TEST(iGc->HasFont());
TFontSpec fontSpec = font->FontSpecInTwips();
TGlyphBitmapType glyphBitmapType = fontSpec.iFontStyle.BitmapType();
TEST(glyphBitmapType == aGlyphBitmapType);
if(fontType[ii].iFontParam & EUnderline)
{
iGc->SetUnderlineStyle(DirectGdi::EUnderlineOn);
}
else if(fontType[ii].iFontParam & EStrikeThrough)
{
iGc->SetStrikethroughStyle(DirectGdi::EStrikethroughOn);
}
if(EDrawTextVerticalDown != aDirection)
{
*coord += font->HeightInPixels() + 5;
}
if(aGlyphStorage && (ii == 0) && (arraySize > 1))
{
aGlyphStorage->CleanGlyphImageCache();
aGlyphStorage->EnforceOOMFailure(ETrue);
}
DrawText(KTextOutput, pt, aDirection, aDrawAdjustment, ii == 1);
if(aGlyphStorage)
{
aGlyphStorage->EnforceOOMFailure(EFalse);
}
if(EDrawTextVerticalDown == aDirection)
{
*coord += font->HeightInPixels() + 5;
}
if(fontType[ii].iFontParam == ENormal)
{
iGc->SetUnderlineStyle(DirectGdi::EUnderlineOff);
iGc->SetStrikethroughStyle(DirectGdi::EStrikethroughOff);
}
iGc->ResetFont();
iFontStore->ReleaseFont(font);
TEST(!iGc->HasFont());
}
region.Close();
if(aClipText)
{
iGc->ResetClippingRegion();
}
// Write the output to file.
//
TESTNOERROR(WriteTargetOutput(iTestParams, testName));
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0003
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9201
REQ9202
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Filling up the glyph image cache
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
1. Fill glyph image storage with the same font but different glyphs until it exceeds its limit and resets the cache.
Repeat this operation for other glyph types
2. Fill glyph image storage with different font and different glyph codes
@SYMTestExpectedResults
Check that Glyph cache storage increments cache size correctly and deletes the least
usable tree.
*/
void CTGlyphImageCache::FillUpCacheL(MFontGlyphImageStorage* aGlyphStorage)
{
if(!aGlyphStorage)
return;
aGlyphStorage->CleanGlyphImageCache();
TBuf<128> testName;
_LIT(KTestName, "GlyphCache_FillUpCache");
if(!iRunningOomTests)
{
INFO_PRINTF1(KTestName);
}
const TSize size(12, 16);
TUint8* buffer = (TUint8*)User::AllocL(size.iWidth * size.iHeight);
CleanupStack::PushL(buffer);
TInt fontId = 10;
TGlyphBitmapType glyphTypeList[] =
{
EMonochromeGlyphBitmap,
EAntiAliasedGlyphBitmap,
EFourColourBlendGlyphBitmap,
};
const TInt numGlyphType = sizeof(glyphTypeList) / sizeof(glyphTypeList[0]);
TESTL(aGlyphStorage->GlyphCacheSize() == 0);
TInt glyphSizeInByte = 0;
TInt expectedSize = 0;
TUint32 glyphCode = 1;
VGImage foregroundImg = VG_INVALID_HANDLE;
VGImage shadowImg = VG_INVALID_HANDLE;
VGImage outlineImg = VG_INVALID_HANDLE;
for(TInt ii = 0; ii < numGlyphType; ii++)
{
TGlyphBitmapType glyphType = glyphTypeList[ii];
//calculate the actual size of the glyph
glyphSizeInByte = GlyphImageSizeInByte(glyphType, size);
TUint maxGlyphSize = aGlyphStorage->MaxGlyphCacheSize() + glyphSizeInByte;
do
{
TEST(expectedSize == aGlyphStorage->GlyphCacheSize());
TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), (TGlyphBitmapType)glyphType, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
glyphCode++;
expectedSize+= glyphSizeInByte;
foregroundImg = VG_INVALID_HANDLE;
shadowImg = VG_INVALID_HANDLE;
outlineImg = VG_INVALID_HANDLE;
}while(expectedSize <= maxGlyphSize);
glyphCode = 1;
expectedSize = 0;
TEST(glyphSizeInByte == aGlyphStorage->GlyphCacheSize());
aGlyphStorage->CleanGlyphImageCache();
}
//now try to filling cache with different fonts and check that last usable font wont be removed
TUint maxGlyphSize = aGlyphStorage->MaxGlyphCacheSize();
glyphSizeInByte = GlyphImageSizeInByte(EMonochromeGlyphBitmap, size);
do
{
TEST(expectedSize == aGlyphStorage->GlyphCacheSize());
TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), EMonochromeGlyphBitmap, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
glyphCode++;
expectedSize+= glyphSizeInByte;
foregroundImg = VG_INVALID_HANDLE;
shadowImg = VG_INVALID_HANDLE;
outlineImg = VG_INVALID_HANDLE;
}while(expectedSize <= maxGlyphSize);
fontId += 10;
glyphCode = 1;
TBool res = aGlyphStorage->GlyphImage(fontId, TChar(glyphCode), EMonochromeGlyphBitmap, buffer, size, &foregroundImg, &shadowImg, &outlineImg);
TEST(glyphSizeInByte == aGlyphStorage->GlyphCacheSize());
TESTNOERROR(res);
RArray<TUint32> listFontId;
aGlyphStorage->FontIdInOrder(listFontId);
TESTL(listFontId.Count() == 1);
TEST(listFontId[0] == fontId);
listFontId.Reset();
CleanupStack::PopAndDestroy(buffer);
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0004
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9201
REQ9202
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Tests filling the glyph image cache with different glyph images
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
Specify glyphs which correspond to different fonts, glyph codes.
Request related VGImages.
Test the cache size is correct after each operation.
Get the driver's MDirectGdiDriverCacheSize interface.
Attempt to set the maximum size of the glyph cache to a size smaller than
the existing cache size.
Attempt to set the maximum size of the glyph cache to a size the same as
the existing cache size.
@SYMTestExpectedResults
Obtained glyph code and cache size must be correct each time.
Setting the maximum glyph cache size to a smaller size than the existing cache
size should fail with error KErrArgument.
Setting the maximum glyph cache size to a size the same as the existing cache
size should pass.
*/
void CTGlyphImageCache::FillCacheL(MFontGlyphImageStorage* aGlyphStorage)
{
ASSERT(aGlyphStorage);
aGlyphStorage->CleanGlyphImageCache();
TBuf<128> testName;
_LIT(KTestName, "GlyphCache_FillCache");
if(!iRunningOomTests)
{
INFO_PRINTF1(KTestName);
}
const TSize smallFontSize = TSize(12, 16);
const TSize smallFont1Size = TSize(10, 14);
const TSize bigFontSize = TSize(18, 24);
const TSize bigFont1Size = TSize(20, 26);
const TInt smallFontId = 10;
const TInt bigFontId = 20;
const TInt smallFont1Id = 30;
const TInt bigFont1Id = 40;
VGImage foregroundImg = VG_INVALID_HANDLE;
VGImage shadowImg = VG_INVALID_HANDLE;
VGImage outlineImg = VG_INVALID_HANDLE;
TUint8* buffer = (TUint8*)User::AllocL(bigFontSize.iWidth * bigFontSize.iHeight);
CleanupStack::PushL(buffer);
TESTL(aGlyphStorage->GlyphCacheSize() == 0);
TInt expectedCacheSize = 0;
TChar glyphCode = TChar(1);
TGlyphBitmapType glyphType = EMonochromeGlyphBitmap;
TBool res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize = GlyphImageSizeInByte(glyphType, smallFontSize);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//try to retrieve the same glyph
res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
//the size should be the same
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//now retrieving the same glyphCode but for the different font
res = aGlyphStorage->GlyphImage(bigFontId, glyphCode, glyphType, buffer, bigFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFontSize);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//last font but different glyphCode
glyphCode = TChar(2);
res = aGlyphStorage->GlyphImage(bigFontId, glyphCode, glyphType, buffer, bigFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFontSize);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//small font and last glyphCode
res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize += GlyphImageSizeInByte(glyphType, smallFontSize);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//now change the type
glyphType = EAntiAliasedGlyphBitmap;
res = aGlyphStorage->GlyphImage(smallFont1Id, glyphCode, glyphType, buffer, smallFont1Size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize += GlyphImageSizeInByte(glyphType, smallFont1Size);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//try again
res = aGlyphStorage->GlyphImage(smallFont1Id, glyphCode, glyphType, buffer, smallFont1Size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//now change the type again
glyphType = EFourColourBlendGlyphBitmap;
res = aGlyphStorage->GlyphImage(bigFont1Id, glyphCode, glyphType, buffer, bigFont1Size, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
expectedCacheSize += GlyphImageSizeInByte(glyphType, bigFont1Size);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//using initial value.
glyphType = EMonochromeGlyphBitmap;
glyphCode = TChar(1);
res = aGlyphStorage->GlyphImage(smallFontId, glyphCode, glyphType, buffer, smallFontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
TEST(expectedCacheSize == aGlyphStorage->GlyphCacheSize());
//get the driver's MDirectGdiDriverCacheSize extension interface and attempt
//to set the maximum cache size to be smaller than the existing cache size
CDirectGdiDriver* driver = CDirectGdiDriver::Static();
TESTL(driver != NULL);
MDirectGdiDriverCacheSize* driverCacheSize = NULL;
res = driver->GetInterface(TUid::Uid(KDirectGdiDriverCacheSizeUid), (TAny*&)driverCacheSize);
TESTNOERRORL(res);
//save the original cache size
TInt originalCacheSize = driverCacheSize->MaxGlyphCacheSize();
//setting the cache size to a size smaller than the existing cache should fail
res = driverCacheSize->SetMaxGlyphCacheSize(aGlyphStorage->GlyphCacheSize()-1);
TEST(res == KErrArgument);
//setting the cache size to the same size as the existing cache should pass
res = driverCacheSize->SetMaxGlyphCacheSize(aGlyphStorage->GlyphCacheSize());
TESTNOERROR(res);
TEST(aGlyphStorage->GlyphCacheSize() == driverCacheSize->MaxGlyphCacheSize());
//reset the original driver cache size
res = driverCacheSize->SetMaxGlyphCacheSize(originalCacheSize);
TESTNOERROR(res);
CleanupStack::PopAndDestroy(buffer);
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0005
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9201
REQ9202
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Tests the ordering font IDs in the glyph image cache.
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
Request glyph images for different fonts.
@SYMTestExpectedResults
List of glyph cache trees must be arranged in order from most used to least used.
*/
void CTGlyphImageCache::FontListIdOrderL(MFontGlyphImageStorage* aGlyphStorage)
{
if(!aGlyphStorage)
return;
aGlyphStorage->CleanGlyphImageCache();
TBuf<128> testName;
_LIT(KTestName, "GlyphCache_FontListIdOrder");
if(!iRunningOomTests)
{
INFO_PRINTF1(KTestName);
}
const TSize fontSize = TSize(12, 16);
TUint8* buffer = (TUint8*)User::AllocL(fontSize.iWidth * fontSize.iHeight);
CleanupStack::PushL(buffer);
TChar glyphCode = TChar(10);
TInt fontId = 10;
VGImage foregroundImg = VG_INVALID_HANDLE;
VGImage shadowImg = VG_INVALID_HANDLE;
VGImage outlineImg = VG_INVALID_HANDLE;
TGlyphBitmapType glyphType = EMonochromeGlyphBitmap;
TInt res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 20;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 30;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
RArray<TUint32> fontListId;
res = aGlyphStorage->FontIdInOrder(fontListId);
if(res != KErrNone)
{
fontListId.Reset();
User::Leave(res);
}
TESTL(fontListId.Count() == 3);
TEST(fontListId[0] == 30);
TEST(fontListId[1] == 20);
TEST(fontListId[2] == 10);
fontListId.Reset();
//call entries again to reorder font id list
fontId = 30;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 20;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 40;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 10;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
fontId = 50;
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TESTNOERRORL(res);
res = aGlyphStorage->FontIdInOrder(fontListId);
if(res != KErrNone)
{
fontListId.Reset();
User::Leave(res);
}
TESTL(fontListId.Count() == 5);
TEST(fontListId[0] == 50);
TEST(fontListId[1] == 10);
TEST(fontListId[2] == 40);
TEST(fontListId[3] == 20);
TEST(fontListId[4] == 30);
fontListId.Reset();
CleanupStack::PopAndDestroy(buffer);
}
/**
@SYMTestCaseID
GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0006
@SYMPREQ
PREQ39
@SYMREQ
REQ9195
REQ9222
REQ9223
REQ9236
REQ9237
@SYMTestCaseDesc
Test the operation of the glyph image cache when sent wrong parameters.
@SYMTestStatus
Implemented
@SYMTestPriority
High
@SYMTestActions
Test requesting of glyph images with invalid paramaters - test an invalid glyph type
and test requesting a glyph image with zero height and one with zero width.
@SYMTestExpectedResults
The function must identify wrong arguments and return the expected error.
*/
void CTGlyphImageCache::WrongParameterL(MFontGlyphImageStorage* aGlyphStorage)
{
_LIT(KTestName, "GlyphCache_WrongParameters");
if(!iRunningOomTests)
{
INFO_PRINTF1(KTestName);
}
aGlyphStorage->CleanGlyphImageCache();
TChar glyphCode = TChar(10);
TInt fontId = 10;
VGImage foregroundImg = VG_INVALID_HANDLE;
VGImage shadowImg = VG_INVALID_HANDLE;
VGImage outlineImg = VG_INVALID_HANDLE;
TSize fontSize = TSize(10, 12);
TUint8* buffer = (TUint8*)User::AllocL(fontSize.iWidth * fontSize.iHeight);
CleanupStack::PushL(buffer);
TGlyphBitmapType glyphType = EDefaultGlyphBitmap; // unsupported
TInt res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, fontSize, &foregroundImg, &shadowImg, &outlineImg);
TEST(res == KErrNotSupported);
TEST(foregroundImg == VG_INVALID_HANDLE);
TEST(shadowImg == VG_INVALID_HANDLE);
TEST(outlineImg == VG_INVALID_HANDLE);
glyphType = EMonochromeGlyphBitmap; // supported
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, TSize(12, 0), &foregroundImg, &shadowImg, &outlineImg);
TEST(res == KErrArgument);
res = aGlyphStorage->GlyphImage(fontId, glyphCode, glyphType, buffer, TSize(0, 12), &foregroundImg, &shadowImg, &outlineImg);
TEST(res == KErrArgument);
TEST(foregroundImg == VG_INVALID_HANDLE);
TEST(shadowImg == VG_INVALID_HANDLE);
TEST(outlineImg == VG_INVALID_HANDLE);
CleanupStack::PopAndDestroy(buffer);
}
TInt CTGlyphImageCache::GlyphImageSizeInByte(TGlyphBitmapType aGlyphType, const TSize& aSize) const
{
TInt glyphSizeInByte = 0;
//calculate the actual size of the glyph
switch(aGlyphType)
{
case EMonochromeGlyphBitmap:
glyphSizeInByte = (((aSize.iWidth + 31) / 32) << 2) * aSize.iHeight;
break;
case EAntiAliasedGlyphBitmap:
glyphSizeInByte = aSize.iWidth * aSize.iHeight;
break;
case EFourColourBlendGlyphBitmap:
glyphSizeInByte = aSize.iWidth * aSize.iHeight;
//we have to allocate memory for shadow and outline bitmap as well
glyphSizeInByte *= 3;
break;
default :
break;
}
return glyphSizeInByte;
}
/**
Draws the text on the screen according its direction and alignment.
*/
void CTGlyphImageCache::DrawText(const TDesC& aText, const TPoint& aPt, DrawTextDirection aDirection, DrawTextAdjustment aDrawAdjustment, TBool aUpdateJustification)
{
const TSize size = iGdiTarget->SizeInPixels();
TRect rect = size;
if(aDirection == EDrawTextHorizontal)
{
switch(aDrawAdjustment)
{
case EDrawFromPoint:
iGc->DrawText(aText, NULL, aPt);
break;
case EDrawInBox:
iGc->SetOrigin(aPt);
rect = TRect(-aPt, size);
iGc->DrawText(aText, NULL, rect);
break;
case EDrawRightAlignment:
rect.iTl = aPt;
rect.iBr.iX -= 30;
iGc->DrawText(aText, NULL, rect, 0, DirectGdi::ERight);
break;
}
}
else if ((aDirection == EDrawTextVerticalDown) || (aDirection == EDrawTextVerticalUp))
{
TBool up = (aDirection==EDrawTextVerticalUp);
switch(aDrawAdjustment)
{
case EDrawFromPoint:
iGc->DrawTextVertical(aText, NULL, aPt, up);
break;
case EDrawInBox:
iGc->SetOrigin(aPt);
rect = TRect(-aPt, size);
if(aUpdateJustification)
{
iGc->SetCharJustification(80, aText.Length());
iGc->UpdateJustificationVertical(aText, NULL, up);
}
iGc->DrawTextVertical(aText, NULL, rect, up);
iGc->SetOrigin(TPoint());
break;
case EDrawRightAlignment:
rect.iTl = aPt;
rect.iBr.iY -= 30;
iGc->DrawTextVertical(aText, NULL, rect, 0, DirectGdi::ERight);
break;
}
}
}
/**
Overrides of base class virtual
@leave Gets system wide error code
@return - TVerdict code
*/
TVerdict CTGlyphImageCache::doTestStepPreambleL()
{
CTDirectGdiStepBase::doTestStepPreambleL();
return TestStepResult();
}
/**
Overrides of base class pure virtual
Our implementation only gets called if the base class doTestStepPreambleL() did
not leave. That being the case, the current test result value will be EPass.
@leave Gets system wide error code
@return TVerdict code
*/
TVerdict CTGlyphImageCache::doTestStepL()
{
// Test for each pixel format
TInt maxPixelFormat = iTargetPixelFormatArray.Count() - 1;
for(TInt targetPixelFormatIndex = maxPixelFormat; targetPixelFormatIndex >= 0 ; targetPixelFormatIndex--)
{
iTestParams.iTargetPixelFormat = iTargetPixelFormatArray[targetPixelFormatIndex];
SetTargetL(iTestParams.iTargetPixelFormat, EOneContextOneTarget, KGlyphCacheWindowSize);
if(maxPixelFormat == targetPixelFormatIndex)
{
iMonotypeFont = DetectMonotypeFontL();
if(!iMonotypeFont)
{
WARN_PRINTF1(_L("!! Due to running the test in environment without monotype fonts, some test cases will not \
be executed! To set up environment with monotype font support, launch ityperast.cmd \
from epoc32\\winscw\\c\\, and then follow the instruction on the screen!!"));
}
else
{
INFO_PRINTF1(_L("Monotype fonts have been detected"));
}
}
RunTestsL();
if(targetPixelFormatIndex == 0)
{
RunOomTestsL();
}
}
CloseTMSGraphicsStep();
return TestStepResult();
}
/**
Overrides of base class pure virtual function
Lists the tests to be run
*/
void CTGlyphImageCache::RunTestsL()
{
MFontGlyphImageStorage* glyphStorage = NULL;
TBool testImageCache = (iUseDirectGdi && !iUseSwDirectGdi);
if(testImageCache)
{
TInt err = iGc->GetInterface(TUid::Uid(KDirectGdiGetGlyphStorageUid), (TAny*&) glyphStorage);
if(err != KErrNone)
{
ERR_PRINTF2(_L("Error while retrieving Glyph Storage Interface, err = %d"), err);
TESTNOERRORL(err);
}
User::LeaveIfNull(glyphStorage);
CleanupStack::PushL(TCleanupItem(CleanCache, glyphStorage));
glyphStorage->CleanGlyphImageCache();
}
if(testImageCache)
{
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
TestRetrieveEntryL(glyphStorage, EAntiAliasedGlyphBitmap);
RecordTestResultL();
glyphStorage->CleanGlyphImageCache();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
TestRetrieveEntryL(glyphStorage, EFourColourBlendGlyphBitmap);
RecordTestResultL();
glyphStorage->CleanGlyphImageCache();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0001"));
TestRetrieveEntryL(glyphStorage, EMonochromeGlyphBitmap);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0006"));
WrongParameterL(glyphStorage);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0005"));
FontListIdOrderL(glyphStorage);
RecordTestResultL();
glyphStorage->CleanGlyphImageCache();
}
if(!iRunningOomTests)//fonts are cached in the array, where memory won't be freed even if the font is released
{
if(testImageCache)
{
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0004"));
FillCacheL(glyphStorage);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0003"));
FillUpCacheL(glyphStorage);
RecordTestResultL();
glyphStorage->CleanGlyphImageCache();
}
for(TInt ii = EDrawTextHorizontal; ii < EDrawTextLast; ii++)
{
for(TInt kk = EDrawFromPoint; kk <= EDrawInBox; kk++)
{
DrawTextDirection direction = (DrawTextDirection) ii;
DrawTextAdjustment adjustment = (DrawTextAdjustment) kk;
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EMonochromeGlyphBitmap, direction, adjustment, EFalse);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EMonochromeGlyphBitmap, direction, adjustment, ETrue);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EAntiAliasedGlyphBitmap, direction, adjustment, EFalse);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EAntiAliasedGlyphBitmap, direction, adjustment, ETrue);
RecordTestResultL();
if(iMonotypeFont)
{
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EFourColourBlendGlyphBitmap, direction, adjustment, EFalse);
RecordTestResultL();
SetTestStepID(_L("GRAPHICS-DIRECTGDI-GLYPHIMAGECACHE-0002"));
TestDrawGlyphL(glyphStorage, EFourColourBlendGlyphBitmap, direction, adjustment, ETrue);
RecordTestResultL();
}
}
}
}
//next set of tests should start from clean cache to garantee consistent results
if(testImageCache)
{
glyphStorage->CleanGlyphImageCache();
CleanupStack::Pop(glyphStorage);
}
}
/**
See if monotype font is installed on the platform we are running on. Monotype font is required
to run the glyph tests that use the glyph bitmap type EFourColourBlendGlyphBitmap to draw
outlined and shadowed fonts.
@return ETrue if monotype is installed, EFalse if it is not installed.
*/
TBool CTGlyphImageCache::DetectMonotypeFontL()
{
CFont *font = NULL;
_LIT(KTestFontTypefaceName,"DejaVu Sans Condensed");
TFontSpec fspec(KTestFontTypefaceName, 12);
fspec.iFontStyle.SetBitmapType(EFourColourBlendGlyphBitmap);
fspec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
fspec.iFontStyle.SetEffects(FontEffect::EOutline, ETrue);
fspec.iFontStyle.SetEffects(FontEffect::EDropShadow, ETrue);
User::LeaveIfError(iFontStore->GetNearestFontToDesignHeightInPixels((CFont*&) font, fspec));
TFontSpec fontSpec = font->FontSpecInTwips();
TGlyphBitmapType glyphBitmapType = fontSpec.iFontStyle.BitmapType();
iFontStore->ReleaseFont(font);
return (EFourColourBlendGlyphBitmap==glyphBitmapType);
}